有一个艰难的。考虑一个由对象列表组成的 ViewModel,其中每个对象都定义一个 int 值,并且其中一些对象还定义了一个 Presets 字典,该字典以表示 UI 中该值的“友好”字符串为键。
这是一个例子...
List<SomeItem> AllItems;
public class SomeItem : INotifyPropertyChanged
{
public SomeItem(int initialValue, Dictionary<int,string> presets)
{
this.CurrentValue = initialValue;
this.Presets = presets;
}
public int CurrentValue{ get; set; } // Shortened for readability. Assume this property supports INPC
public Dictionary<int,string> Presets{ get; private set; }
}
UI 的目标是如果项目没有预设,用户可以输入他们想要的任何 int 值。但是,如果有 预设,我们希望将它们限制为这些值,并将它们作为字典中的友好名称显示在 UI 中。
我们的第一个尝试是使用一个 TextBox 和一个 ComboBox,根据是否有预设来修改它们的可见性,就像这样......
<ComboBox ItemsSource="{Binding Presets}"
DisplayMemberPath="Key"
SelectedValuePath="Value"
SelectedValue="{Binding CurrentValue, Mode=TwoWay}"
Visibility={Binding HasPresets, Converter=...}">
<TextBox Text="{Binding CurrentValue}"
Visibility={Binding HasPresets, Converter...}" /> // Assume the inverse of the combo
...但是当我们在支持虚拟化的列表的 DataTemplate 中使用它时,组合偶尔会显示空白。我相信是因为当项目被重复使用并且 DataContext 发生变化时,SelectedValue 在 ItemsSource 之前更新意味着可能没有预设值可以匹配,因此建议的 SelectedValue 值被控件抛出,然后 ItemsSource 更新,但没有选定的值,因此它显示为空白。
我的下一个想法(无论如何我们更喜欢)是只使用一个显示预设名称但实际上绑定(bind)到值的文本框,然后使用一个转换器来发挥它的魔力,让用户输入友好的名称或实际值。如果用户键入的内容不是有效值或预设值,我们只会抛出一个错误。如果没有预设,它只会充当值的传递。
但是,我不确定如何将预设传递给转换器。您不能在 ConverterParameter 上设置绑定(bind)以这种方式传递它们,如果您使用多重绑定(bind),那么我不确定如何构造“ConvertBack”调用,因为我也需要它们传入,而不是送回。
我认为正确的方法是在 ViewModel 中实现 UiValue,我们只需像这样绑定(bind)它...
<TextBox Text="{Binding UiValue}" />
...然后将本应在转换器中的代码移动到该属性的 getter/setter 实现,或者如果没有预设,则只是传递给 Value。然而,这似乎在 ViewModel 中发生了太多逻辑,而它应该在 View 中(ala 转换器或类似的)。然后,也许这正是 ViewModel 的重点。我不知道。欢迎提出想法。
最佳答案
就个人而言,我会按照您的建议将“转换器代码”放入属性中……我认为将代码放在那里没有任何问题。事实上,它可能比将它放在 Converter
中更好,因为那样您也可以轻松地测试它。
抱歉,这不是一个很好的答案,但我觉得你的问题至少值得一个。
关于c# - 在显示该项目上也定义的预设列表中的友好名称时绑定(bind)到值的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18736899/