如何通过偏移将组合框绑定到另一个值而不是实际值?

How to bind combo box to another value than the actual by offsetting it?

我有一个标记如下的组合框。

<ComboBox SelectedIndex="{Binding Path=Bonkey}">
  <ComboBoxItem Content="Monkey" />
  <ComboBoxItem Content="Donkey" />
</ComboBox>

根据下面的声明,我正在绑定一个 Bonkey 字段类型为整数的对象。

class Thingy
{
  public int Bonkey {get; set; }
  ...
}

虽然它工作得很好并且符合预期,但有一个编程技术问题让我彻夜难眠。手动标记中生成的索引是 0 和 1。但是,我知道整数的值将是 1 和 2。(即 Monkey 与组合相关时索引为 0框项目,但它在用作数据源的对象中的实际值为 1。类似地,Monkey 在组合框的项目中具有索引 1,但它对应于对象中的 2。)

我的中间解决方案是在设置数据上下文之前在构造函数中关闭 1,然后在处理视图时启动 1。它的工作,但我真的不能骄傲,可以这么说。

public SomeDialog(Thingy thingy)
{
  InitializeComponent();
  thingy.Bonkey--;
  DataContext = thingy;
}
...
private void Cancel_Click(object sender, RoutedEventArgs eventArgs)
{
  DialogResult = false;
  DataContext.Bonkey++;
  Close();
}
...
private void Submit_Click(object sender, RoutedEventArgs eventArgs)
{
  DataContext.Bonkey++;
  ...
}

我怎样才能做得更多,嗯...不要脸?

  1. 我找不到任何属性来明确设置组合框中项目的索引。
  2. 我试过使用转换器,但不知何故,我要么在组合框中得到空的东西(没有预选),要么一些奇怪的错误消息告诉我我做了一个 boo-boo(因为我不是即使确定这是否是一个好方法我也会放弃)。
  3. 谷歌搜索给出了一堆结果,none 其中让我清楚地了解了如何抵消值边界(尽管老实说,我怀疑我可能使用了太奇怪的关键字,因为它看起来这样的问题以前肯定讨论过)。

有许多问题涉及偏移量和 IValueConverter 实现。但是浏览它们,我没有看到一个解决绑定偏移量的特定场景的;许多问题涉及已经让转换器工作但遇到其他问题的人,而其他问题涉及的场景在某种程度上比这个更复杂。

所以,这是一个非常简单的偏移转换器实现:

class OffsetValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int offset = int.Parse((string)parameter);

        return (int)value - offset;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int offset = int.Parse((string)parameter);

        return (int)value + offset;
    }
}

这样使用:

<ComboBox SelectedIndex="{Binding OffsetValue,
                          Converter={StaticResource offsetValueConverter1},
                          ConverterParameter=1}"/>

当然,您声明了一个资源以使转换器的实例可用,例如:

<Window.Resources>
  <l:OffsetValueConverter x:Key="offsetValueConverter1"/>
</Window.Resources>

还有其他的实现选项,比如给转换器实例本身一个属性来设置来控制偏移量,或者指定偏移量为一个实际的int值,这样它就不会必须进行解析,但这些方法有其自身的局限性,例如不能为不同的偏移重用相同的实例,或者分别需要在 XAML 中进行更详细的声明。我认为以上在便利性和效率之间取得了很好的平衡。


另见相关问题:
How can I bind one property to another property, offset by a specific amount?
Applying transforms from DataTemplates in WPF

There are others,不过这些好像和你自己的场景关系最密切