有一个类似的问题,但答案似乎与原始问题不符。
我有一个 DataTemplate,里面有 3 个组合框。前两个工作正常,但第三个会引发编译错误。
<ComboBox ItemsSource="{x:Bind ListOne, Mode=OneWay}"
SelectedItem="{Binding SelectedOne, Mode=TwoWay}"
DisplayMemberPath="Name"/>
<ComboBox ItemsSource="{x:Bind ListTwo}"
SelectedItem="{x:Bind SelectedTwo, Mode=TwoWay, Converter={StaticResource GenericConverter}}"
DisplayMemberPath="Name"/>
<ComboBox ItemsSource="{x:Bind ListThree}"
SelectedItem="{x:Bind SelectedThree, Mode=TwoWay}"
DisplayMemberPath="Name"/>
对于 ListOne,“绑定(bind)”按原样完美工作。
对于 ListTwo,“x: Bind”只有在添加值转换器时才有效。 “GenericConverter”仅返回传入的“值”。除此之外,它什么都不做。
对于 ListThree,没有值转换器,编译器会抛出错误:
"Invalid binding path 'SelectedThree': Cannot bind type 'IdNameVm' to 'SystemObject' without a converter.
在所有情况下,ItemSource 都是一个 ObservableCollection,所选项目的类型为 IdNameVm。
使用转换器是可行的,但被迫在 x: Bind 上放置一个虚拟转换器感觉是错误的,只是为了让 XAML 进行编译。
根据要求,这里是 ObservableCollection 加上 IdNameVm 的定义方式:
public ObservableCollection<IdNameVm> ListOne { get; set; }
public class IdNameVm : BindableBase
{
private int _id;
private string _name;
public int Id
{
get { return _id; }
set { Set(ref _id, value); }
}
public string Name
{
get { return _name; }
set { Set(ref _name, value); }
}
protected bool Equals(IdNameVm other)
{
return Id == other.Id;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((IdNameVm)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = Id;
return hashCode;
}
}
}
最佳答案
如果您查看 ComboBox 的文档,您会看到 ItemsSource 和 SelectedItem属性都是对象类型。控件在不知道它正在处理什么类型的 View 模型的情况下运行。因此,您基本上可以将任何类型的集合传递给 ItemsSource。 SelectedItem 在不知道它正在处理什么类型的对象的情况下工作。
这种行为在传统的双向 {Binding} 中运行良好,因为绑定(bind)是在运行时评估的。所以{Binding}可以在运行时将SelectItem的对象类型转换为IdNameVm。
但是,{x:Bind} 的情况有些不同。正如您所注意到的,单向绑定(bind)有效——这是因为您的 ObservableCollection 可以隐式转换为对象(ItemsSource 的类型)和 IdNameVm 转换为对象(SelectedItem 的类型)。但是双向绑定(bind)将不再有效,因为编译器无法将对象(SelectedItem 的类型)转换为 IdNameVm。你需要一个转换器。
就像您可以在 C# 中执行此操作一样:
IdNameVm vm = new IdNameVm();
object selectedItem = vm;
但是你不能这样做:
IdNameVm vm = new IdNameVm();
object selectedItem = vm;
IdNameVm vm2 = selectedItem; // You need: IdNameVm vm2 = (IdNameVm)selectedItem;
注释中的cast是XAML中的converter。
在这些情况下,最简单的方法是使用传统的{Binding}。
关于c# - UWP-x :Bind Mode=TwoWay throws errors without converter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36158167/