【问题标题】:Binding issues with RadioButtonRadioButton 的绑定问题
【发布时间】:2012-03-01 13:06:19
【问题描述】:

我有一个看似简单的任务,这让我很头疼,希望能得到一些帮助。

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

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

我已经输入了 together a sample app 来说明问题所在。要重现,请运行应用程序并按照以下步骤操作:

  1. 在组合框中选择“One” => MyPropery 已选中,MyProperty2 未选中。
  2. 在组合框中选择“三” => MyPropery 已选中,MyProperty2 未选中。
  3. 仍然选择“三”时,单击 MyProperty2 => 选中 MyProperty2(也在调试输出窗口中指示)
  4. 在组合框中选择“一个” => MyPropery 已选中,MyProperty2 未选中。 注意调试窗口如何显示对象“三”的 MyProperty2 是如何设置为 false 的
  5. 在组合框中选择“三” => 现在两个单选按钮都未选中(由于 #4)。

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

有人可以解释一下为什么在第 4 步中当 ContentPresenter 交换视图时设置属性,以及可以做些什么?

【问题讨论】:

    标签: c# wpf data-binding


    【解决方案1】:

    DataTemplates 被缓存,所以OneThree 使用完全相同的UserControl。您可以通过向控件添加Loaded 事件并在选项之间切换来验证这一点。

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

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

    【讨论】:

    • +1。 Rachels 绝对正确:DataTemplate 生成的 UIElements 被缓存,并且 UI 中的 CheckBox Grouping 被触发到 ViewModel 中,从而弄乱了您的复选框状态。
    • 所以基本上,GroupName 和 MVVM/DataTemplates 不能混用。 :( 我不能使用 ListBox 解决方案,因为我必须将 RadioButtons 彼此分开放置。我想我将不得不使用常规复选框并改为处理 VM 中的分组。感谢您的帮助。
    【解决方案2】:

    这似乎是一个错误(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;
    }
    

    这解决了问题(不是很好的解决方案,而是一种解决方法)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-23
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-17
      • 2015-02-08
      • 1970-01-01
      相关资源
      最近更新 更多