WPF单选按钮组与自定义用户控件的冲突

4

我实例化了两个相同的UserControl。它们都有单选按钮并共享GroupName。当我选择其中一个时,所有其他单选按钮都会取消选择,即使它们属于不同的UserControl实例。

如何避免这种GroupName冲突?

以下是一个最小化的示例以说明此问题:

Main xaml

<Window x:Class="RadioDemo.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">
    <StackPanel>
        <UserControl x:Name="First"/>
        <UserControl x:Name="Second"/>
    </StackPanel>
</Window>

主代码后端

public MainWindow()
{
    InitializeComponent();
    Loaded += MainWindow_Loaded;
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    First.Content = new MyRadio();
    Second.Content = new MyRadio();
}

我的收音机 XAML

<UserControl x:Class="RadioDemo.MyRadio"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
        <RadioButton GroupName="G" x:Name="RadioOne" Content="RadioOne"/>
        <RadioButton GroupName="G" x:Name="RadioTwo" Content="RadioTwo"/>
    </StackPanel>
</UserControl>

我意识到我在评论一个已经有接受答案的老问题,但是你真的需要 GroupName 分配吗?在这种情况下,RadioButton 应该已经通过它们的容器(StackPanel)逻辑分组了。第二个用户控件实例中的 RadioButton 应该已经在它们自己的 StackPanel 中拥有自己独立的逻辑分组。据我所知,你真正需要 GroupName 的唯一时候是当你有在同一个容器中的 RadioButton,但想要将它们分别分组时。 - nedmech
@nedmech 说得有道理。我没有设置来测试这个,但是如果你的单选按钮在同一个StackPanel中像你想要的那样取消选择,可能就不需要显式分组了。- 我依稀记得这与我们被迫使用的UI库有关,该库具有实现上的宝石,导致了解决方法和黑客行为。 - Johannes
1个回答

7
一旦用户控件加载完成,您可以动态地创建组名值。
XAML:
<StackPanel>
    <RadioButton GroupName="{Binding GroupNameValue}" x:Name="RadioOne" Content="RadioOne"/>
    <RadioButton GroupName="{Binding GroupNameValue}" x:Name="RadioTwo" Content="RadioTwo"/>
</StackPanel>

视图模型:

private string groupNameValue = Guid.NewGuid().ToString();

public string GroupNameValue
{
    protected get { return this.groupNameValue; }
    set
    {
        this.SetProperty(ref this.groupNameValue, value);
    }
}

SetPropertyINotifyPropertyChanged 接口的实现。
在这里我使用 Guid 作为唯一性的保证,但你可以使用任何你想要的。

使用 C# 6.0 可以简化代码:

private string groupNameValue = Guid.NewGuid().ToString();

public string GroupNameValue => this.groupNameValue;

3
另一种解决方案是在UserControl上声明一个依赖属性来保存GroupName。这样,需要时仍然可以将相同的GroupName附加到多个UC。简洁解释:通过添加一个依赖属性在不同的UserControl之间共享GroupName。 - Funk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接