简体   繁体   中英

C# WPF value converter receiving entire collection instead of single item as value parameter?

I have a C# WPF 4.51 application. On one of my XAML forms I have a list box that has its ItemsSource property bound to a property in my main ViewModel that is of type Collection . When the Collection was of type string , everything worked fine and I saw the collection of strings in the list box.

But then I changed the type in the Collection to a class named ObservableStringExt . The class has two fields: StrItem that contains the string I want displayed in the list box, and IsSelected , a supporting field. I then created a value converter to extract the StrItem field and return it.

However, when I look at the targetType passed to the Convert() method of the value converter I see a type of IEnumerable . Given that the Count property in that parameter matches the number of list items expected, it looks like the Convert() method is receiving a reference to the entire Collection instead of ObservableStringExt , the type of each item in the Collection. This of course is a problem. What is causing this? I have done this sort of thing many times in Windows Phone and WinRT (windows store apps) many times without trouble.

Here is the code for the value converter:

public class ObservableStringExtToStrItem : IValueConverter
{
    // The targetType of the value received is of type IEnumerable, not ObservableStringExt.
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is ObservableStringExt)
            return (value as ObservableStringExt).StrItem;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Below is the XAML code for the list box. Note Commands_FrequentyUsed is a property of type ObservableCollectionWithFile found in the main view model, which is the data context for the entire form:

<ListBox x:Name="listFrequentlyUsedCommands"
             Width="278"
             Height="236"
             Margin="30,103,0,0"
             HorizontalAlignment="Left"
             VerticalAlignment="Top"
             ItemsSource="{Binding Commands_FrequentyUsed.Collection,
                                   Converter={StaticResource ObservableStringExtToStrItem}}" />

Here is the code for the class that contains the Collection that the list box binds to and the class the Collection contains:

public class ObservableStringExt
{
    public string StrItem { get; set;}
    public bool IsSelected{ get; set; }
}

public class ObservableCollectionWithFile : BaseNotifyPropertyChanged
{

    public const string CollectionPropertyName = "Collection";
    private ObservableCollection<ObservableStringExt> _observableCollection = new ObservableCollection<ObservableStringExt>();

    public ObservableCollection<ObservableStringExt> Collection
    {
        get { return _observableCollection; }
        private set { SetField(ref _observableCollection, value); }
    }
} // public class ObservableCollectionWithFile

I just had the same problem. Not sure how it should normally work, but changing the converter to also convert list of items helped (I found this easier than creating a separate converter for List)

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var list = value as IEnumerable<ObservableStringExt>;
    if (list != null)
    {
        return list.Select(x => Convert(x, typeof(string), null, culture));
    }
    if (value is ObservableStringExt)
        return (value as ObservableStringExt).StrItem;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM