将转换应用到 ComboBox 下拉菜单中的所有元素

Apply conversion to all elements in a ComboBox drop down menu

我正在尝试根据 ViewModel 中的特定 属性 仅更改 ComboBox 中所有项目内容的文本。我创建了一个 DataTemplate,其中 Binding 的值为 SelectedValue,具体的 属性 我想将转换基于 SomeProperty:

<ComboBox ItemsSource="{Binding Path=ChannelValues}"
          SelectedValue="{Binding Path=Channel, Mode=TwoWay}">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <TextBlock>
        <TextBlock.Text>
          <MultiBinding Converter="{StaticResource ResourceKey=ChannelNumConverter}">
            <Binding Path="SelectedValue" 
                     RelativeSource="{RelativeSource AncestorType={x:Type ComboBox}}" />
            <Binding Path="DataContext.SomeProperty"
                     ElementName="DataContextView" />
          </MultiBinding>
        </TextBlock.Text>
      </TextBlock>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</ComboBox>

这似乎有效,希望下拉列表中的所有值都更改为翻译后的 SelectedValue。我试过用 Text 替换 SelectedValue,但这也不起作用。有没有办法将此转换应用于下拉列表中的所有值(同样,仅更改显示的值,而不更改基础数据)?

更新 - ViewModel

// Populate somewhere with values
private ObservableCollection<ushort> mChannelValues = new ObservableCollection<ushort>();

public ObservableCollection<ushort> ChannelValues
{
   get
   {
      return mChannelValues;
   }
}

private ushort mChannelNum;
public ushort Channel
{
   get
   {
      return mChannelNum;
   }
   set
   {
      if (mChannelNum != value)
      {
         mChannelNum = value;
         OnPropertyChanged(new PropertyChangedEventArgs("Channel"));
      }
   }
}

private ushort mSomeProperty;
public ushort SomeProperty
{
   get
   {
      return mSomeProperty;
   }
   set
   {
      if (mSomeProperty!= value)
      {
         mSomeProperty= value;
         OnPropertyChanged(new PropertyChangedEventArgs("SomeProperty"));
      }
   }
}

更新 2 - 简单转换器

public object Convert(
   object[] values,
   Type targetType,
   object parameter,
   CultureInfo culture)
{
   if (targetType != typeof(string))
      throw new InvalidOperationException("The target must be a string");
   if ((values[0] != null) && (!(values[0] is ushort)))
      throw new InvalidOperationException("The channel must be an short");
   if ((values[1] != null) && (!(values[1] is ushort)))
      throw new InvalidOperationException("The some property must be a ushort");

   ushort ushort_val = ushort.Parse((string)values[0]);
   ushort ushort_some_property = ushort.Parse((string)values[1]);

   switch (ushort_some_property)
   {
      case 0:
         return (ushort_val + 1).ToString();
      case 1:
         return (ushort_val + 7).ToString();
      case 2:
         return (ushort_val + 2).ToString();
      default:
         return ushort_val.ToString();
   }
}

您可以使用 SomeProperty 作为 ConverterParameter

而不是使用 MultiBinding
<TextBlock Text="{Binding Converter={StaticResource ResourceKey=ChannelNumConverter}, ConverterParameter={Binding SomeProperty}}"/>

在转换器中:

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

问题实际上是您的 itemTemplate 应用于 A​​LL! 组合框中的项目,其转换器实际上处理当前选定的项目和导致所有项目中的值相等的某些属性.

此时的方法不是问题。您只需在视图模型中绑定当前文本的值而不是选定的值。

这会将视图模型中的两个值合并到文本框中显示的结果中,而无需任何递归更新。

终于知道怎么做了。下面是 xaml 将转换器应用于下拉列表中的所有元素:

<ComboBox ItemsSource="{Binding Path=ChannelValues}"
          SelectedValue="{Binding Path=Channel, Mode=TwoWay}">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <TextBlock>
        <TextBlock.Text>
          <MultiBinding Converter="{StaticResource ResourceKey=ChannelNumConverter}">
            <Binding />
            <Binding Path="DataContext.SomeProperty"
                     RelativeSource="{RelativeSource Mode=FindAncestor,
                                      AncestorType=local:DataContextView}" />
          </MultiBinding>
        </TextBlock.Text>
      </TextBlock>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</ComboBox>