-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RadioButtons with the same GroupName
will affect each other over windows if window is closed
#2995
Comments
From the open-source codes, we can find that the radio button auto checks the focus root as the group name scope: KeyboardNavigation.GetVisualRoot(this) |
Before the issue is fixed, we can try to solve it by adding a <StackPanel local:RadioButtonFix.IsScope="True">
<Border>
<RadioButton GroupName="{local:RadioButtonFix A}" Content="Option 1" />
</Border>
<Border>
<RadioButton GroupName="{local:RadioButtonFix A}" Content="Option 2" />
</Border>
<Border>
<RadioButton GroupName="{local:RadioButtonFix A}" Content="Option 3" />
</Border>
</StackPanel> |
Something must be wrong with your setup, if I add RadioButtons with GroupName to a window and then create two instances of the same window (which obviously have the same group name since they have the same XAML) they don't affect each other. I'll have a look at your repro scenario. |
@weltkante Yes, according to your description, they actually don't affect each other. In my scene, you should:
|
Ok I think I understood what you are reporting, your title is misleading. GroupName will not affect other windows.
I agree that there's a bug somewhere, but I'm not sure its about GroupName, it might also be about bindings. Another option to work around is adding a |
You are right the bug is in private void Button_Click(object sender, RoutedEventArgs e)
{
new MainWindow().Show();
new MainWindow();
new MainWindow();
} As such I'd summarize it as this: All disconnected UI elements share the same radio button group scope, which leads to bugs when disconnected UI is still connected via bindings. Closed windows act as disconnected UI, but they are not the only case. |
@weltkante Thanks for your efforts to simplify this issue and to hit the critical codes. |
临时解决方案 public static class GroupNameProvider
{
public static readonly DependencyProperty BuildScopeProperty = DependencyProperty.RegisterAttached(
"BuildScope", typeof(bool), typeof(GroupNameProvider), new PropertyMetadata(PropertyChangedCallback));
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is bool value && value == true)
{
SetGroupNameA(d, Guid.NewGuid().ToString("N"));
}
}
public static void SetBuildScope(DependencyObject element, bool value)
{
element.SetValue(BuildScopeProperty, value);
}
public static bool GetBuildScope(DependencyObject element)
{
return (bool) element.GetValue(BuildScopeProperty);
}
public static readonly DependencyProperty GroupNameAProperty = DependencyProperty.RegisterAttached(
"GroupNameA", typeof(string), typeof(GroupNameProvider), new PropertyMetadata(default(string)));
private static void SetGroupNameA(DependencyObject element, string value)
{
element.SetValue(GroupNameAProperty, value);
}
public static string GetGroupNameA(DependencyObject element)
{
return (string) element.GetValue(GroupNameAProperty);
}
} <Grid x:Name="Panel" local:GroupNameProvider.BuildScope="True">
<RadioButton IsChecked="{Binding Foo}"
GroupName="{Binding ElementName=Panel,Path=(local:GroupNameProvider.GroupNameA)}"/>
</Grid> |
simplified your demo: <StackPanel>
<Border>
<RadioButton GroupName="A" IsChecked="{Binding Bar, Source={x:Static local:Foo.Instance}}" Content="Option 1" />
</Border>
<Border>
<RadioButton GroupName="A" Content="Option 2" />
</Border>
<Border>
<RadioButton GroupName="A" Content="Option 3" />
</Border>
</StackPanel>
<StackPanel>
<Border>
<RadioButton GroupName="A" IsChecked="{Binding Bar, Source={x:Static local:Foo.Instance}}" Content="Option 1" />
</Border>
<Border>
<RadioButton GroupName="A" Content="Option 2" />
</Border>
<Border>
<RadioButton GroupName="A" Content="Option 3" />
</Border>
</StackPanel> just open window one time |
Yes this is what happens, but when you do it intentionally its not a bug. The point of the bug report is that everything not attached to a visual root will start sharing their radiobutton groups. So while you have two windows open they can use the same radiobutton groupnames and they will be distinct, but if you close/hide them they start to share their groups. If the radiobuttons were databound this will lead to a feedback loop. The important part of the repro is, that it initially works (groups are distinct), and only starts breaking if you start closing windows, because then they change into the broken state. |
@NaBian Your simpler code really describes the reason for this issue, but not describes the pain for this issue. Also @weltkante . If radio buttons with the same group names affect each other even across different windows, then we have to give up the embedded group name feature because our visible radio buttons may be influenced by the ones which should have been destroyed. This means we have to use the method from @xinyuehtx for nearly every radio button with group names if our programs have to open different window instances of one window class. |
I have this same issue and it took me days to figure out what was wrong. In my case I have a UserControl that uses GroupName to control RadioButton grouping in a Grid (I can't add them to StackPanel or GroupBox for graphical reasons). When I duplicate an object, I remove the UserControl from my window and create a new one to show the duplicate. I then modify the radiobuttons in the duplicate. If I then go to the original object, I see my radiobuttons update to match the properties. But when I go back to the duplicate, the radiobuttons have changed to match the original object. |
Analysis so far - While registering the radio buttons, the reference to them in hashtable is added as a weak reference which should allow the GC to collect it when the window is closed. However, it looks like there is some other pointer strongly referencing the radiobutton even after the window is closed (which is why it is still not null in this check). Continuing to investigate where is the reference being held for the radio button after the window is closed. |
来信悉知,我会尽快回复
——黄腾霄
|
@walterlv We have merged the above PR which fixes the issue. Can you verify if it solves the issue. |
Awesome @harshit7962 |
@harshit7962 I've tested it on .NET 8 rc2 and find that it is fixed. Thank you! |
Problem description:
If some
RadioButton
s are in the same group, they should check and uncheck each other. If we create two windows both contain the same XAML RadioButton groups, we'll find that theRadioButton
s are separated into two windows. However, if one window is closed, theRadioButton
s in the other window will affect those in the closed one.This code below shows how to set the
GroupName
, but it's recommended to read the minimal reproduction at the end of this issue to know all the details.By running the minimal reproduction source code, you'll see the expected behavior and the broken behavior and I've posted the gifs below.
Expected behavior:
Actual behavior:
Minimal repro:
The GitHub repo:
The keys:
RadioButton
s in a window XAML;RadioButton
s in different windows affect each other, so I bind the firstRadioButton.IsChecked
to a singleton. This means:false
. At last, all values arefalse
. As a result, no radio button can be checked.If all the windows are open, all behave as expected:
If the previous windows are closed, then the radio buttons start to affect each other:
The XAML code:
The C# code:
The text was updated successfully, but these errors were encountered: