Skip to content
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

Implicitly grouped RadioButtons are treated as in the same group #1299

Closed
nxtn opened this issue Sep 9, 2019 · 9 comments
Closed

Implicitly grouped RadioButtons are treated as in the same group #1299

nxtn opened this issue Sep 9, 2019 · 9 comments
Labels
area-RadioButtons duplicate This issue or pull request already exists needs-winui-3 Indicates that feature can only be done in WinUI 3.0 or beyond. (needs winui 3) team-Controls Issue for the Controls team

Comments

@nxtn
Copy link
Contributor

nxtn commented Sep 9, 2019

Describe the bug

Only one of implicitly grouped RadioButtons can be set to IsChecked programmatically.

Steps to reproduce the bug

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Button>
            <Button.Flyout>
                <Flyout>
                    <StackPanel>
                        <RadioButton x:Name="RadioButton1" IsChecked="True" />
                    </StackPanel>
                </Flyout>
            </Button.Flyout>
        </Button>
        <Button>
            <Button.Flyout>
                <Flyout>
                    <StackPanel>
                        <RadioButton x:Name="RadioButton2" IsChecked="True" />
                    </StackPanel>
                </Flyout>
            </Button.Flyout>
        </Button>
    </Grid>
</Page>
using System.Diagnostics;
using Windows.UI.Xaml.Controls;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
            Debug.WriteLine(RadioButton1.IsChecked);
            Debug.WriteLine(RadioButton2.IsChecked);
        }
    }
}

Expected behavior

True
True

Actual behavior

False
True

Version Info

Windows 10 version Saw the problem?
May 2019 Update (18362) Yes
Device form factor Saw the problem?
Desktop Yes
@jevansaks
Copy link
Member

Seems by design? Unnamed RadioButtons are all in the same "group" and will find each other to make sure they stay mutually exclusive. Try setting GroupName on one of them to something non-default.

@nxtn
Copy link
Contributor Author

nxtn commented Sep 10, 2019

They are not exclusive. You can check one RadioButton in each group after the initialization.

@jevansaks
Copy link
Member

If you just have two "ungrouped" RadioButtons in a page, they are exclusive. I think the bug is that at runtime if a flyout is open then changing one RadioButton doesn't affect the other because the closed flyout isn't in the tree and the RadioButton can't find its friend anymore.

@nxtn
Copy link
Contributor Author

nxtn commented Sep 10, 2019

This behavior is not relevant to Flyouts. See the following example with Flyouts changed to StackPanels.

If RadioButton1.IsChecked is set to true programmatically, another will be unchecked.

But both can be checked manually by user input.

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0">
            <StackPanel>
                <RadioButton x:Name="RadioButton1" IsChecked="True" />
            </StackPanel>
        </StackPanel>
        <StackPanel Grid.Row="1">
            <StackPanel>
                <RadioButton x:Name="RadioButton2" IsChecked="True" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Page>
using System.Diagnostics;
using Windows.UI.Xaml.Controls;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();

            Debug.WriteLine(RadioButton1.IsChecked); // False
            Debug.WriteLine(RadioButton2.IsChecked); // True

            RadioButton1.IsChecked = true;

            Debug.WriteLine(RadioButton1.IsChecked); // True
            Debug.WriteLine(RadioButton2.IsChecked); // False

            // Click RadioButton2

            RadioButton2.Checked += (sender, e) =>
            {
                Debug.WriteLine(RadioButton1.IsChecked); // True
                Debug.WriteLine(RadioButton2.IsChecked); // True
            };
        }
    }
}
False
True
True
False
True
True

@jevansaks
Copy link
Member

In your later repro, if you wait until things have "settled", are both IsChecked properties still true? Sometimes these events fire before all the values are up to date (since we're calling the callback synchronously during state changes).

Backing up a bit, what's the scenario you're trying to achieve?

@nxtn
Copy link
Contributor Author

nxtn commented Sep 12, 2019

Before clicking
image
After clicking
image

The doc says "Put them inside the same parent container" to group radio buttons. The behaviors of initialization and IsChecked property setter in UWP is inconsistent with both Windows Forms and WPF.

WPF after initialization
image

Windows Forms source

if (isChecked)
{
    Control parent = ParentInternal;
    if (parent != null)
    {
        ControlCollection children = parent.Controls;
        for (int i = 0; i < children.Count; i++)
        {
            Control ctl = children[i];
            if (ctl != this && ctl is RadioButton)
            {
                RadioButton button = (RadioButton)ctl;
                if (button.autoCheck && button.Checked)
                {
                    PropertyDescriptor propDesc = TypeDescriptor.GetProperties(this)["Checked"];
                    propDesc.SetValue(button, false);
                }
            }
        }
    }
}

@jevansaks
Copy link
Member

Right, there's clearly a bug here with the RadioButtons in flyouts. Looking at the code I suspect the bug may be that all unparented RadioButtons are treated as having the "same parent". And you may run into this case when setting IsChecked on elements during tree construction.

I can leave this bug open as "needs winui 3" but it wouldn't help you now. But maybe this information would be useful for you to work around the bug.

@jevansaks jevansaks reopened this Sep 12, 2019
@jevansaks jevansaks added area-RadioButtons needs-winui-3 Indicates that feature can only be done in WinUI 3.0 or beyond. (needs winui 3) labels Sep 12, 2019
@nxtn nxtn changed the title Only the last IsChecked="True" attribute of implicitly grouped RadioButtons takes effect Implicitly grouped RadioButtons are treated as in the same group Sep 12, 2019
@jevansaks jevansaks added the team-Controls Issue for the Controls team label Nov 7, 2019
@StephenLPeters StephenLPeters added the duplicate This issue or pull request already exists label Mar 10, 2020
@StephenLPeters
Copy link
Contributor

duping to #2081 as the discussion there has more info

@robloo
Copy link
Contributor

robloo commented Jul 7, 2020

This one is pretty bad. I ran across it trying to make the ColorPickerButton

@msft-github-bot msft-github-bot added the needs-triage Issue needs to be triaged by the area owners label Jul 7, 2020
@ranjeshj ranjeshj removed the needs-triage Issue needs to be triaged by the area owners label Jul 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-RadioButtons duplicate This issue or pull request already exists needs-winui-3 Indicates that feature can only be done in WinUI 3.0 or beyond. (needs winui 3) team-Controls Issue for the Controls team
Projects
None yet
Development

No branches or pull requests

6 participants