目标:通过xaml将ListBox(或ComboBox)的SelectedItem绑定到对象的实例,我想通过视图模型设置对象的选定实例,并将其反映在ListBox或ComboBox上。
<ComboBox x:Name="cboServers" HorizontalAlignment="Left" Margin="535,694,0,0" VerticalAlignment="Top" Width="225"
ItemsSource="{Binding Settings.Servers}"
SelectedItem="{Binding Settings.SelectedServer, Mode=TwoWay}"
DisplayMemberPath="UserFriendlyName">
C#模型查看代码
public ObservableCollection<AutoSyncServer> Servers { get; set; }
private AutoSyncServer _selectedServer;
public AutoSyncServer SelectedServer
{
get { return _selectedServer;}
set
{
_selectedServer = value;
OnPropertyChanged("SelectedServer");
}
}
列表或组合框正确填充。选择ListBox或ComboBox上的项目将正确设置SelectedServer对象。
但是,如果我尝试在C#中编写一个set语句,例如:
Servers.Add(newServer);
SelectedServer = newServer;
ListBox或ComboBox将正确添加项目,并且将在MVVM模型上正确设置SelectedServer对象,但前端不会反映此选择。
在这种特定情况下,会读取一个xml文件,说明用户最后选择了什么,当窗口打开时,ComboBox没有选择任何内容(虽然服务器都在其中正确加载)
这里缺少什么?
答案 0 :(得分:2)
SelectedItem
中的实际对象必须是Servers
集合中Object.ReferenceEquals(a, b)
集合中的对象实例。不只是相同的名称和ID(或其他)属性;同一个确切的类实例。
人们遇到这种情况的典型案例是在多个地方反序列化等效项目。 Servers
有一组反序列化的AutoSyncServer
个实例,而Settings.SelectedServer
是一个单独反序列化的AutoSyncServer
个实例,它与Servers
中的某个项具有相同的属性值。但它仍然是一个不同的对象,ComboBox
无法知道你打算不这样做。
如果AutoSyncServer.Equals()
的两个实例逻辑等效,则可以覆盖AutoSyncServer
以返回true。我不喜欢这样做,因为它改变了该类的=
运算符的语义,之前曾经咬过我。但这是一个选择。
另一个选择是拥有一个AutoSyncServer
的规范静态集合,并确保每个类从中获取其实例。
鉴于上述情况,我不明白为什么这段代码不起作用:
Servers.Add(newServer);
SelectedServer = newServer;
newServer
位于Servers
后,应该可以选择。我测试了它,它正如你所期望的那样为我工作。
答案 1 :(得分:0)
我认为你必须避免“子绑定”,它们在视图要求时工作一次,但之后不能很好 Settings.SelectedServer ==&gt; SelectedServer
如果你评论OnServerChanged?.Invoke(this, _selectedServer);
发生了什么?它有效吗?