我有一个看似简单的任务,这让我很头疼,并会感激一些帮助。
我想要完成的是将两个布尔值绑定到两个RadioButton
的IsChecked属性,共享相同的GroupName
(因此一次只检查一个)。
我面临的问题是,当ContentPresenter的内容即将发生变化时(通过绑定到ComboBox的SelectedItem),当前内容会接收对Property-setter的调用,该属性具有相同属性但是从即将成为新内容的视图模型。 (!)最终结果是视图模型发生了变化,尽管没有点击与相关属性绑定的RadioButton。
我已将together a sample app用于显示问题。要重现,请运行该应用并按照以下步骤操作:
如果在#3和#4之间,首先在组合框中选择“Two”以使ContentPresenter显示另一个视图(通过DataTemplate选择),问题不会出现!?
有人可以解释一下,当ContentPresenter交换视图时,为什么在第4步设置属性,以及可以采取哪些措施?
答案 0 :(得分:1)
DataTemplates已缓存,因此One
和Three
都使用完全相同的UserControl
。您可以通过向控件添加Loaded
事件并在选项之间切换来验证这一点。
当您切换到Two
并返回Three
时,WPf只会从缓存中重新绘制该项,但切换到One
并返回Three
,它更改对象后面的DataContext
。我认为这是导致问题的原因,因为它似乎在删除DataContext之前清除了第二个RadioButton IsChecked,因此最终结果是Property2被设置为false。如果One
和Three
都选择了第二个单选按钮,则不会发生这种情况。
通常在这种情况下,我会让VM包含ObservableCollection<T> Items
和int SelectedIndex
。然后我将使用已被覆盖的ListBox
绘制UI以使用RadioButtons作为项目。这样,一次只能选择一个项目,并且只有一个属性用于存储所选项目。
答案 1 :(得分:0)
这似乎是一个错误(ContentPresenter的内容发生了变化,但DataContext却没有。)
但我可以为您提供解决方案。在您的示例中,执行以下操作(MainWindow.xaml):
<StackPanel>
<ComboBox ItemsSource="{Binding MyItems, Mode=OneWay}" Name="cmbBox" DisplayMemberPath="ID" SelectionChanged="cmbBox_SelectionChanged"/>
<ContentPresenter Name="cp1" />
</StackPanel>
在cmbBox_SelectionChanged中查找以下内容:
private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
cp1.Content = null;
cp1.DataContext = null;
cp1.Content = cmbBox.SelectedItem;
}
这解决了问题(不是一个很好的解决方案,而是一种解决方法)。