4

我确定这种行为是已知的,但我无法用谷歌搜索它。我有以下代码:

<Window x:Class="ContentControlListDataTemplateKacke.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <TabControl ItemsSource="{Binding Items}">
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Label Content="{Binding Name}" />
                        <RadioButton Content="Option1" IsChecked="{Binding Option1}" />
                        <RadioButton Content="Option2" IsChecked="{Binding Option2}" />
                    </StackPanel>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </DockPanel>
</Window>

代码隐藏很简单:

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}

ViewModel 看起来像这样:

public class ViewModel : NotificationObject
{
    public ViewModel()
    {
        Items = new ObservableCollection<Item>
        {
            new Item {Name = "1", Option1 = true},
            new Item {Name = "2", Option2 = true}
        };
    }

    public ObservableCollection<Item> Items { get; set; }
}

和这样的项目:

public class Item : NotificationObject
{
    public string Name { get; set; }

    private bool _option1;
    public bool Option1
    {
        get { return _option1; }
        set
        {
            _option1 = value;
            RaisePropertyChanged(() => Option1);
        }
    }

    private bool _option2;
    public bool Option2
    {
        get { return _option2; }
        set
        {
            _option2 = value;
            RaisePropertyChanged(() => Option2);
        }
    }
}

我正在使用 Prism,因此 RaisePropertyChanged 会引发 PropertyChanged 事件。选择第二个选项卡,然后是第一个选项卡,然后再次选择第二个选项卡,瞧,第二个选项卡上的 RadioButtons 被取消选择。

为什么?

除了 Rachels 之外的另一种解决方案

我的一位同事刚刚想到将 RadioButtons 的 GroupName 属性绑定到每个项目的唯一字符串。只需将 RadioButtons 的声明更改为:

<RadioButton GroupName="{Binding Name}" Content="Option1" IsChecked="{Binding Option1}" />
<RadioButton GroupName="{Binding Name}" Content="Option2" IsChecked="{Binding Option2}" />

如果 Name-property 对于所有项目都是唯一的(就像我的问题一样),它会起作用。

4

2 回答 2

1

WPF 将所有单选按钮作为同一组的一部分读取,并且在单选按钮组中一次只能选择一项。

加载顺序如下:

  • 加载选项卡1
  • 加载 Tab1.Radio1。IsChecked = 真
  • 加载 Tab1.Radio2。IsChecked = True,因此设置 Tab1.Radio2.IsChecked = False

  • 单击选项卡 2

  • 加载选项卡2
  • 加载 Tab2.Radio1。IsChecked = True,因此设置 Tab1.Radio2.IsChecked = False
  • 加载 Tab2.Radio2。IsChecked = True,因此设置 Tab2.Radio1.IsChecked = False

  • 到目前为止,Tab2.Radio2 是唯一选中的,并且所有其他 Radio 都已加载且未选中,因此它们的 DataBound 值已更新为 false。

  • 单击选项卡 1

  • 加载 Tab1.Radio1。IsChecked = 假
  • 加载 Tab1.Radio2。IsChecked = 假

如果您的单选按钮不相关并且可以同时检查,我建议切换到CheckBoxes

如果它们要被分组并且一次只能选择一个项目,我建议切换到使用ListBox绘制的RadioButtons,并且只将 存储SelectedOption在您的ViewModel

这是我通常使用的样式:

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>

                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

它是这样使用的:

<ListBox ItemsSource="{Binding Options}"
         SelectedValue="{Binding SelectedValue}"
         Style="{StaticResource RadioButtonListBoxStyle}" />
于 2012-07-18T17:06:35.837 回答
0

我曾经遇到过一个与此非常相似的问题,当我在视图之间切换时,文本被清除了。如果我没记错的话,以下解决方案是有效的。

  • 绑定OneWay到属性并使用属性标记这些绑定的属性。
  • 每次加载视图(以及视图模型)时,对上述属性使用反射来查找绑定的属性。
  • PropertyChanged为每个属性触发一个事件以正确更新视图。

我认为这是由于使用默认设置加载视图而不是在加载时查询属性,因为没有任何事件引发PropertyChanged事件。

此外,这不是您的问题的一部分,但您可以直接在 XAML 中设置数据上下文(通过 Window 中的 DataContext 属性),这样 Visual Studio 就不必有明确的代码隐藏文件。

于 2012-07-18T15:33:00.973 回答