开发者

Access ComboBoxItem DisplayValue

I have a comboBox that has an ItemsSource of a list of objects. So the DisplayMemberPath is set to a particular property of the object. Of course this means that the correct value is displayed in the ComboBoxItem.

My issue is that I would like to 开发者_运维知识库be able to get that "Value" that is returned by the DisplayMemberPath in XAML so that I can bind it to something else. i.e. I would like to have a "DisplayText" property on the ComboBoxItem.

Of course I don't have this, so, does anyone know of a way to get this value without traversing down into the template of the ComboBoxItem looking for the ContentHost?

If you're interested in my specific use of this, I'm trying to do this on the style of the ComboBox:

....
<Setter Property="ItemContainerStyle">
   <Setter.Value>
      <Style>
        <Setter 
             Property="AutomationProperties.AutomationId" 
             Value="{Binding RelativeSource={RelativeSource Self}, Path=MagicPathForDisplayedText}"/>
....

Of course Path=Content works just fine if you're just binding your ItemsSource to properties, but when it's an Object with a DisplayMemberPath, Content will be that Object.

Thanks for any help or re-framing of the problem.


The easiest way to handle problems like this is usually Attached Properties and Behaviors.

You could create two attached properties called DisplayMemberPath and DisplayText, then you bind DisplayMemberPath to the parent ComboBox DisplayMemberPath and in the PropertyChangedCallback you set up a binding of your own with the same path for DisplayText. After that you have a property which you can bind to

<Style x:Key="ComboBoxStyle" TargetType="ComboBox">
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="ComboBoxItem">
                <Setter Property="behaviors:DisplayTextBehavior.DisplayMemberPath"
                        Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBox}},
                                        Path=DisplayMemberPath}"/>
                <Setter Property="AutomationProperties.AutomationId"
                        Value="{Binding RelativeSource={RelativeSource Self},
                                        Path=(behaviors:DisplayTextBehavior.DisplayText)}"/>
            </Style>
        </Setter.Value>                    
    </Setter>
</Style>

DisplayTextBehavior

public class DisplayTextBehavior
{
    public static DependencyProperty DisplayMemberPathProperty =
        DependencyProperty.RegisterAttached("DisplayMemberPath",
                                            typeof(string),
                                            typeof(DisplayTextBehavior),
                                            new FrameworkPropertyMetadata("", DisplayMemberPathChanged));
    public static string GetDisplayMemberPath(DependencyObject obj)
    {
        return (string)obj.GetValue(DisplayMemberPathProperty);
    }
    public static void SetDisplayMemberPath(DependencyObject obj, string value)
    {
        obj.SetValue(DisplayMemberPathProperty, value);
    }

    private static void DisplayMemberPathChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        ComboBoxItem comboBoxItem = sender as ComboBoxItem;
        string displayMemberPath = GetDisplayMemberPath(comboBoxItem);
        comboBoxItem.SetBinding(DisplayTextProperty, new Binding(displayMemberPath));
    }

    public static DependencyProperty DisplayTextProperty =
        DependencyProperty.RegisterAttached("DisplayText",
                                            typeof(string),
                                            typeof(DisplayTextBehavior),
                                            new FrameworkPropertyMetadata(""));
    public static string GetDisplayText(DependencyObject obj)
    {
        return (string)obj.GetValue(DisplayTextProperty);
    }
    public static void SetDisplayText(DependencyObject obj, string value)
    {
        obj.SetValue(DisplayTextProperty, value);
    }
}


You could bind an intermediate Object in the ViewModel to the SelectedItem property on the Combobox. Then also Bind your other display item to that intermediate object. Then when the PropertyChanged event is fired by selecting an item, the display will also update via the event chain.


Are you using SelectedValuePath? If not you could could set it the same as DisplayMemberPath and then the selected value is available as SelectedValue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜