简体   繁体   中英

Databinding a combobox of types and overriding their display string

This doesn't seem to make my combobox display the friendlier names. I'm not sure what I'm doing wrong.

<ComboBox ItemsSource="{Binding MyTypes, Mode=OneTime}"
          SelectedItem="{Binding SelectedType}"/>
public sealed class MyType : IMyInterface
{
    public override string ToString()
    {
        return "Friendlier Name";
    }
}

Also, i attempted to use an IValueConverter (which didn't work)...

<ComboBox ItemsSource="{Binding MyTypes, Mode=OneTime}"
          MemberDisplayPath="{Binding Converter={StaticResource MyConverter}}"
          SelectedItem="{Binding SelectedType}"/>
[ValueConversion(typeof(Type), typeof(String))]
public sealed class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var type = value as Type;

        if (type == null)
        {
            return DependencyProperty.UnsetValue;
        }

        return type.ToString();
    }

    ...
}

The problem is the IValueConverter seems to only get my ViewModel as it's value being passed in... so not sure what's going on there.

Use a DataTemplate and apply your converter there.

<ComboBox.ItemTemplate>
    <DataTemplate>
         <TextBlock Text="{Binding Converter={StaticResource MyConverter}}"/>
    </DataTemplate>
</ComboBox.ItemTemplate>

I fixed your IValueConverter for you... as long as you are binding to Type objects, you'll need to create an instance and use the ToString() override on that instance instead. Keep in mind that this can get messy if you're classes have some crazy construction logic to them.

[ValueConversion(typeof(Type), typeof(String))]
internal sealed class TypeNameConverter : IValueConverter
{
    private static readonly IDictionary<Type, string> TypeNameCache = new Dictionary<Type, string>();
    private static readonly object TypeNameCacheLock = new Object();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var type = value as Type;

        if (type == null)
        {
            return DependencyProperty.UnsetValue;
        }

        string result;

        lock (TypeNameCacheLock)
        {
            if (!TypeNameCache.TryGetValue(type, out result))
            {
                var instance = Activator.CreateInstance(type);

                result = instance.ToString();

                TypeNameCache.Add(type, result);
            }
        }

        return result;
    }

    ...
}

This portion was copied from HB's answer, and is necessary for it to work :)

<ComboBox.ItemTemplate>
    <DataTemplate>
         <TextBlock Text="{Binding Converter={StaticResource MyConverter}}"/>
    </DataTemplate>
</ComboBox.ItemTemplate>

The property you're using is actually called DisplayMemberPath , and it works much more simply than your code would suggest.

Change your code like this:

public sealed class MyType : IMyInterface
{
    public string FriendlyName
    {
        get { return "Friendlier Name"; }
    }
}

Then in your Xaml set DisplayMemberPath="FriendlyName" and you're done.

(Throw your converter away, I would suggest. If you're converting a whole class into a string value then there's usually an easier way of doing it.)

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