【问题标题】:How to force a WPF multi-binding to update when inside a ComboBox TemplateSelector?如何在 ComboBox TemplateSelector 内强制更新 WPF 多绑定?
【发布时间】:2017-03-22 07:57:26
【问题描述】:

作为前言,这个问题来自扩展 this answer 关于如何使所选项目看起来与 ComboBox 中的下拉项目不同。

我正在尝试使我的自定义选定项目使用来自 ComboBox 的 Tag 属性的信息。由于我需要使用转换器,因此我使用mutli-converter 以便能够将“我自己”发送到转换类。因此,我有这两个模板:

<DataTemplate x:Key="SelectedItemTemplate">
    <StackPanel Orientation="Horizontal">
        <TextBlock>
            <TextBlock.Text>
                <MultiBinding Converter="{StaticResource SelectedConverter}">
                    <Binding RelativeSource="{RelativeSource Self}" />
                    <Binding StringFormat="This is here so it's called every time" />
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
        <TextBlock Text="{Binding}" />
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="DropDownItemsTemplate">
    <TextBlock Grid.Column="0" Text="{Binding}"  Margin="0,0,10,0" VerticalAlignment="Center" />
</DataTemplate>

还有我的转换器:

class SelectedConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var retVal = "";

        // The value passed in should be the TextBox in the ComboBoxItem
        var element = values[0] as DependencyObject;

        // Try to find it's parent RoleComboBox
        while (element != null && !(element is ComboBox))
        {
            element = VisualTreeHelper.GetParent(element);
        }

        // If we didn't find anything, return an empty string
        if (element == null) return retVal;

        // Otherwise, get the role from the ComboBox
        var tag = (element as ComboBox).Tag;

        if (tag?.ToString().Contains("Custom") ?? false)
        {
            retVal = "Custom Stuff ";
        }

        return retVal;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

组合框的 XAML

<ComboBox Name="myComboBox" Grid.Column="0" Tag="My Custom Tag" ItemTemplateSelector="{StaticResource CbTemplateSelector}">
    <ComboBox.Items>
        <ComboBoxItem Content="A" />
        <ComboBoxItem Content="B" />
        <ComboBoxItem Content="C" />
        <ComboBoxItem Content="D" />
        <ComboBoxItem Content="E" />
    </ComboBox.Items>
</ComboBox>

所有这些都很好地产生了这个:

现在,我需要做的是在我更改 Tag 属性时将“Custom Stuff C”更改为其他内容。到目前为止,它只会在我更改所选项目时更改,但我需要更改它而无需用户将其更改为 D,然后再更改回 C。

通过研究,我尝试使用以下代码强制更新,但它不起作用。

myComboBox.GetBindingExpression(ComboBox.ItemTemplateProperty)?.UpdateTarget();
myComboBox.GetBindingExpression(ComboBox.ItemTemplateSelectorProperty)?.UpdateTarget();
myComboBox.GetBindingExpression(ComboBox.SelectionBoxItemTemplateProperty)?.UpdateTarget();
myComboBox.GetBindingExpression(ComboBox.TemplateProperty)?.UpdateTarget();
myComboBox.UpdateLayout();
myComboBox.OnSelectionChanged(new SelectionChangedEventArgs(SelectionChangedEvent, new List<bool> { }, new List<bool> { }));

请注意,我确实有一个继承自ComboBox 的自定义控件,因此我确实可以访问受保护的方法(上面最后一行代码的工作方式)。我只是将那部分提取出来,以便提供一小部分可重现的代码。

目前,我不确定还可以尝试什么。那么如何根据我的操作方式强制我的绑定更新呢?

【问题讨论】:

  • 尝试直接绑定到ComboBox.Tag,像这样:{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}, Path=Tag}
  • @Evk,我不能这样做,因为我不想要标签中的实际内容。我想使用标签中的内容使其成为其他内容。因此是转换器。
  • 我理解,但我的意思是,在您的多重绑定中,不是这个“”,而是如上所述直接绑定到 Tag(但仍然使用多重绑定)。虽然不确定为什么要使用多重绑定,但在转换器中您只使用第一个参数,因此您也可以使用转换器的常规绑定。
  • 要点是:无论您使用多重绑定还是常规转换器 - 如果您直接绑定(在多个绑定之一中)到 ComboBox.Tag - 此标签更改时将刷新绑定。
  • @Evk,现在就试试。初步似乎工作。想把你的答案移到答案吗?

标签: c# wpf xaml data-binding imultivalueconverter


【解决方案1】:

与其绑定到 self 然后在代码中搜索父组合框,只需使用内置方法即可:

<TextBlock.Text>
    <MultiBinding Converter="{StaticResource SelectedConverter}">
        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}" Path="Tag" />
        <Binding StringFormat="This is here so it's called every time" />
    </MultiBinding>
</TextBlock.Text>

作为奖励,如果您直接绑定到 ComboBox.Tag - 整个多重绑定将在该 Tag 更改时刷新。

【讨论】:

    猜你喜欢
    • 2013-09-01
    • 2012-05-12
    • 2011-08-06
    • 2012-06-18
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2011-02-28
    • 2010-10-12
    相关资源
    最近更新 更多