您的怀疑是正确的,这种方式破坏了MVVM模型并且没有使用可以简化工作的机制,例如
System.Windows.Interactivity中的触发器,它在
Expression Blend SDK中可用。
在getter中加载数据是在自找麻烦。它将您的模型绑定到数据访问代码,使测试变得更加困难,并通过在同一属性中混合不同的关注点使代码变得更加复杂。此外,墨菲定律规定,在某些时候,您只想设置属性而不从数据库重新加载。
更好的解决方案是将数据加载代码提取到单独的方法中,该方法可以由命令或触发器调用。该方法将修改Oc2集合的内容或仅用新集合替换它。无论哪种情况,属性setter都会引发适当的通知并更新第二个组合框。
以下示例来自类似SO问题中
fabien's answer的回答:
<ComboBox x:Name="fileComboBox" ItemsSource="{Binding FileList, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction
Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding SelectedItems,
ElementName=fileComboBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
大多数框架都支持这种设计。
Caliburn.Micro提供了
actions,当UI事件发生时,将调用ViewModel方法,并提供了一种快捷语法,以避免编写触发器XAML和相应的命令。它只是将事件连接到ViewModel方法。XAML可以简单地写成这样:
<ComboBox x:Name="Oc1"
cal:Message.Attach="[Event SelectionChanged] =
[Action ReloadFor($this.SelectedItem)]" />
$this
值是另一种简写,用于引用 ComboBox 本身。
如果您不想使用触发器,可以将您的组合框的 SelectedItem 属性绑定到 ViewModel 属性,并在此属性更改时执行 Reload 方法,例如:
<ComboBox ... SelectedItem={Binding CurrentOC2,Mode=TwoWay} />