通过ViewModel MVVM WPF

时间:2017-03-20 15:37:48

标签: wpf mvvm selecteditem

目标:通过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没有选择任何内容(虽然服务器都在其中正确加载)

这里缺少什么?

2 个答案:

答案 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);发生了什么?它有效吗?