2012-03-01 113 views
4

我有一个看似简单的任务,这是让我头痛,并希望得到一些帮助。绑定问题与RadioButton

我想完成的是将两个布尔值绑定到两个RadioButton的IsChecked属性,共享相同的GroupName(因此一次只检查一个)。

我面临的问题是,当ContentPresenter的内容即将更改(通过绑定到ComboBox的SelectedItem)时,当前内容会接收对具有相同属性值的Property-setter的调用而是从即将成为新内容的视图模型。 (!)最终的结果是尽管没有点击与有问题的属性绑定的RadioButton,但视图模型发生了变化。

我已经把together a sample app显示出这个问题。要重现,运行应用程序,并按照下列步骤操作:在下拉列表

  1. 选择“一” => MyPropery检查,MyProperty2不是。
  2. 在combobox中选择“Three”=>选中MyPropery,MyProperty2不是。
  3. 虽然仍然选择“三”,单击MyProperty2 => MyProperty2选中(也显示在调试输出窗口中)
  4. 选择“One”在combobox => MyPropery被选中,MyProperty2不是。 请注意调试窗口如何显示对象“Three”的MyProperty2如何设置为false
  5. 在组合框中选择“Three”=>现在选中两个Radiobutton(由于#4)。

如果在#3和#4之间,首先在组合框中选择“Two”以使ContentPresenter显示另一个视图(通过DataTemplate选择),则问题不会出现!

有人可以解释为什么在ContentPresenter交换视图时为什么该属性设置为步骤#4,并且可以做些什么?

回答

1

数据模板被高速缓存,所以OneThree使用完全相同UserControl。您可以通过向控件添加Loaded事件并在选项之间切换来验证此情况。

当您切换到Two和回Three,WPF将简单地重新绘制从缓存中的项目,但是切换到One和回Three,它改变了对象后面的DataContext。我认为这是造成这个问题,因为它似乎是在删除DataContext之前清除第二个RadioButton IsChecked,所以最终结果是Property2被设置为false。如果OneThree都选择了第二个单选按钮,则不会发生这种情况。

通常在这种情况下,我会让虚拟机包含一个ObservableCollection<T> Items和一个int SelectedIndex。然后,我将使用已被覆盖的ListBox来绘制UI,以便使用RadioButton作为项目。这样一次只能选择一个项目,并且只有一个属性用于存储所选项目。

+0

+1。 Rachels绝对正确:缓存DataTemplate生成的UIElements,并且UI中的CheckBox分组被激活到ViewModel中,从而搞乱了复选框的状态。 – SvenG 2012-03-01 15:35:57

+0

所以基本上,GroupName和MVVM/DataTemplates不会混合。 :(我无法使用ListBox解决方案,因为我必须将RadioButton分开放置,我想我必须使用常规复选框,而不是在虚拟机中处理组合。感谢您的帮助。 – Per 2012-03-01 16:01:37

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; 
} 

这解决了这个问题(没有很好的解决方案,但有解决方法)。