Пользовательские элементы управления WPF на отдельных вкладках: почему имя группы radioobutton разделено между вкладками?

Я использую элемент управления вкладками WPF для представления отдельных повторяющихся экземпляров пользовательского элемента управления. то есть Tab1 для параметров Item1, Tab2 для параметров Item2 и т.д.

Кажется, что имена групп переключателей разделяются между вкладками. Что происходит?

Простой пример:

В окне есть вкладки. Каждая вкладка содержит пользовательский элемент управления.

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lib="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Grid>
    <TabControl Margin="0,0,0,100" Name="tabControl1">
        <TabItem Header="tabItem1" Name="tabItem1">
            <lib:UserControl1 x:Name="userControlInTab1" />
        </TabItem>
        <TabItem Header="tabItem2" Name="tabItem2">
            <lib:UserControl1 x:Name="userControlInTab2" />
        </TabItem>
    </TabControl>
</Grid>

Пользовательский элемент управления - это просто две радиообъекты в группе:

<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="50" Width="100">
<StackPanel>
    <RadioButton GroupName="Group1" Name="radiobutton1" Content="option1" IsChecked="True" />
    <RadioButton GroupName="Group1" Name="radiobutton2" Content="option2" />
</StackPanel>

Если вы запустите это приложение, вы увидите, что только флажок radioobutton1 во второй вкладке отмечен, несмотря на то, что usercontrol, определяющий его, всегда нужно проверять при запуске.

Кроме того, установка радиообмена, как отмечено в коде позади, кажется, позволяет снять все радиообъекты на других вкладках!

Похоже, что все работает отлично под управлением мыши (т.е. вкладки независимы).

Наконец, пользовательские элементы управления кажутся отдельными экземплярами. Например, я пробовал это с помощью ползунков на пользовательских элементах управления, и они ведут себя независимо друг от друга по вкладкам. Как и должно быть.

Спасибо за помощь. Я искал широко, но безрезультатно. Конечно, я не единственный человек, у которого была эта проблема. Я использую VS2008.

Ответ 1

Без настройки GroupName он работает. Это не является абсолютно необходимым, так как RadioButtons в одном контейнере автоматически группируются в любом случае. Например:

<UserControl x:Class="WpfApplication1.UserControl1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Height="50" Width="100">
    <StackPanel>
        <StackPanel>
            <RadioButton  Name="radiobutton1" Content="option1" IsChecked="True" />
            <RadioButton  Name="radiobutton2" Content="option2" />
        </StackPanel>
        <StackPanel>
            <RadioButton  Name="radiobutton3" Content="option3" IsChecked="True" />
            <RadioButton  Name="radiobutton4" Content="option4" />
        </StackPanel>
    </StackPanel>
</UserControl>

Ответ 2

Это по дизайну:

вся точка GroupName должна позволять вам определять переключатели которые действуют как группа без необходимости содержания одного и того же родителя Панель.

Прочтите эту статью для подробного объяснения.

Говоря кратко, существуют два решения для двух разных случаев:

  • Если у вас есть все логически связанные переключатели в одном контейнере, не указывать имя_группы. В этом случае радиокнопки автоматически образуют группу, которая не зависит от каких-либо других групп переключателей.

  • Если вы разделили логически связанные переключатели на нескольких панелях для целей макета, прочитайте статью за длинное объяснение, что делать.

Ответ 3

У меня была ситуация, когда дизайн не позволял разделять радиостанции на отдельные стеки. Итак, что я сделал, удалил GroupName из xaml и принудительно включил группировку из модели. Эта идея возникла из этой ссылки, например

private bool _useGaugeOpen;
public bool UseGaugeOpen
{
    get { return _useGaugeOpen; }
    set
    {
        _useGaugeOpen = value;
        _useATGOpen = !value;
        RaisePropertyChanged("UseATGOpen");            
    }
}
private bool _useATGOpen;
public bool UseATGOpen
{
    get { return _useATGOpen; }
    set
    {
         _useATGOpen = value;
         _useGaugeOpen = !value;
         RaisePropertyChanged("UseGaugeOpen");
    }
 }