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

CheckBox has the same visual as false when IsChecked's bound value is set to null #18629

Open
AndrewKeepCoding opened this issue Oct 31, 2024 · 11 comments
Assignees
Labels
kind/bug Something isn't working

Comments

@AndrewKeepCoding
Copy link
Contributor

AndrewKeepCoding commented Oct 31, 2024

Current behavior

  • CheckBox has the same visual as false [ ] when IsChecked's bound value is set to null.
  • CheckBox has the expected visual, [x] -> [-] -> [ ], with click operations.
  • CheckBox has the "indeterminate" visual [-] when <CheckBox IsChecked="{x:Null}" IsThreeState="True" />.
  • WinUI's CheckBox doesn't have this issue.
  • It tried WASDK, WASM and Desktop but this behavior was reproduced only on WASDK.

Expected behavior

CheckBox should have the "indeterminate" visual [-] when IsChecked's bound value is set to null.

How to reproduce it (as minimally and precisely as possible)

No response

Workaround

No response

Works on UWP/WinUI

Yes

Environment

No response

NuGet package version(s)

Uno.Sdk v5.4.10

Affected platforms

Windows (WinAppSDK)

IDE

Visual Studio 2022

IDE version

Microsoft Visual Studio Enterprise 2022 (64-bit) - Preview Version 17.12.0 Preview 4.0

Relevant plugins

No response

Anything else we need to know?

No response

@AndrewKeepCoding AndrewKeepCoding added difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification labels Oct 31, 2024
@morning4coffe-dev
Copy link
Member

Thanks @AndrewKeepCoding, I will take a look into investigating a bit more

@morning4coffe-dev morning4coffe-dev self-assigned this Oct 31, 2024
@morning4coffe-dev
Copy link
Member

@AndrewKeepCoding I have been trying to repro the issue this morning, but I wasn't able to replicate the issue. This is my repro:

    <StackPanel HorizontalAlignment="Center"
                VerticalAlignment="Center">
        <TextBlock AutomationProperties.AutomationId="HelloTextBlock"
                   Text="Hello Uno Platform!"
                   HorizontalAlignment="Center" />

        <CheckBox Content="Sample IsThreeState CheckBox"
                  IsChecked="{x:Bind ViewModel.CheckBoxValue, Mode=TwoWay}"
                  IsThreeState="True" />

        <CheckBox Content="Sample CheckBox"
                  IsChecked="{x:Bind ViewModel.CheckBoxValue, Mode=TwoWay}" />

        <Button Content="Set to Null"
                Click="Button_Click"
                Margin="0,20,0,0" />
    </StackPanel>
public partial class MainPageVM : ObservableObject
{
    [ObservableProperty]
    private bool? checkBoxValue = null;

    public void OnSetToNullClick()
    {
        CheckBoxValue = null;
    }
}

CheckBoxIndeterminate.zip

which results in this for both WinUI and Desktop (Skia):
image

Do you see any adjustments I have to make to repro? Or is it specific to some other target? Thanks.

@AndrewKeepCoding
Copy link
Contributor Author

AndrewKeepCoding commented Nov 1, 2024

@morning4coffe-dev I tried your project and yeah, it works. 😅

Can you check this repro project?
UnoFluentApp.zip

@AndrewKeepCoding
Copy link
Contributor Author

AndrewKeepCoding commented Nov 1, 2024

I found out that you are using x:Bind and I'm using Binding.

MainPage.xaml

<Button
    Click="Button_Click"
    Content="Click" />

<CheckBox
    IsChecked="{Binding BooleanValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    IsThreeState="True" />

MainViewModel.cs

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private bool? booleanValue = null;

    public void DoSomething()
    {
        BooleanValue = BooleanValue switch
        {
            true => false,
            false => null,
            _ => true
        };
    }
}

@morning4coffe-dev
Copy link
Member

@AndrewKeepCoding Hmmm... this is interesting. I was able to run your repro project, but this is what I am seeing (left WinUI, right Skia Desktop):

checkbox.mp4

As this is the behavior with x:Bind on WinUI as well, I feel like the behavior is the correct one on our side and there might be issue with WinUI. What do you think @MartinZikmund?

@AndrewKeepCoding
Copy link
Contributor Author

I'm so sorry @morning4coffe-dev . I was completely wrong. WinUI has the same behavior:

Recording.2024-11-01.233122.mp4

I must have used x:Bind when I checked before.

@MartinZikmund
Copy link
Member

@AndrewKeepCoding so I guess this would be something to report on WinUI repo? Otherwise I think this can be closed

@djaroszewicz
Copy link

Hey, I would like to add that there is also a problem on x:Bind. If we have focus on a checkbox, the indeterminate state is displayed, but leaving the cursor out of the checkbox (bool? = null), changes the visual state to true, even though the observable property is still null.

@MartinZikmund MartinZikmund reopened this Nov 6, 2024
@MartinZikmund MartinZikmund removed triage/untriaged Indicates an issue requires triaging or verification difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. labels Nov 6, 2024
@morning4coffe-dev
Copy link
Member

@djaroszewicz

Thank you for sharing. Which platform are you seeing this on? Would you be able to help me repro the issue on the sample project I shared, please? (a screenshot of the behavior you are seeing should be good) CheckBoxIndeterminate.zip Thank you.

@djaroszewicz
Copy link

djaroszewicz commented Nov 7, 2024

Forgive me, I missed to add that the problem occurs when we wrap the checkbox in a Button that performs some additional logic underneath. In the case of a simple checkbox, the problem does not occur. I realise that a better approach is to use Microsoft Behaviors, but it seems to me that this should also work in this case. I'm adding code, let me add a possible video in my free time.

Xaml:

<Button Command="{Binding ChangeSelectAllCommand}" ToolTipService.ToolTip="Select/unselect all">
                    <Button.Content>
                        <Grid>
                            <CheckBox IsEnabled="True" IsThreeState="True" IsChecked="{Binding SelectAll, Mode=OneWay, 
                            UpdateSourceTrigger=PropertyChanged}"/>
                        </Grid>
                    </Button.Content>
                </Button>

                <Button Margin="0, 5, 0, 0" Command="{Binding ChangeSelectAllIsHitVisibleCommand}" ToolTipService.ToolTip="Select/unselect all">
                    <Button.Content>
                        <Grid>
                            <CheckBox IsEnabled="True" IsThreeState="True" IsHitTestVisible="False" IsChecked="{Binding SelectAllIsHitVisibleFalse, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Grid>
                    </Button.Content>
                </Button>

                <Grid Margin="0, 10, 0, 0">
                    <CheckBox IsEnabled="True" IsThreeState="True" IsChecked="{Binding SelectAllForCheckbox, Mode=TwoWay}">
                        <interactivity:Interaction.Behaviors>
                            <interactions:EventTriggerBehavior EventName="Click">
                                <interactions:InvokeCommandAction
                                    Command ="{Binding TextBlockDoubleTappedCommand}"/>
                            </interactions:EventTriggerBehavior>
                        </interactivity:Interaction.Behaviors>
                    </CheckBox>
                </Grid>

                <Button Margin="0, 15, 0, 0" Command="{Binding ChangeNormalCheckboxCommand}" ToolTipService.ToolTip="Select/unselect all">
                    <Button.Content>
                        <Grid>
                            <CheckBox IsEnabled="True" IsHitTestVisible="False" IsChecked="{Binding NormalCheckbox, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                        </Grid>
                    </Button.Content>
                </Button>

View Model:

    [ObservableProperty]
    private bool _normalCheckbox = false;

    [ObservableProperty]
    private bool? _selectAll = false;

    [ObservableProperty]
    private bool? _selectAllIsHitVisibleFalse = false;

    [ObservableProperty]
    private bool? _selectAllForCheckbox = false;

    [RelayCommand]
    private void ChangeNormalCheckbox()
    {
        if (NormalCheckbox == true)
            NormalCheckbox = false;
        else NormalCheckbox = true;  
    }

    [RelayCommand]
    private void ChangeSelectAll()
    {
        if (SelectAll == true)
            SelectAll = false;
        else if (SelectAll == false)
            SelectAll = null;
        else
            SelectAll = true;
    }

    [RelayCommand]
    private void ChangeSelectAllIsHitVisible()
    {
        if (SelectAllIsHitVisibleFalse == true)
            SelectAllIsHitVisibleFalse = false;
        else if (SelectAllIsHitVisibleFalse == false)
            SelectAllIsHitVisibleFalse = null;
        else
            SelectAllIsHitVisibleFalse = true;
    }

@djaroszewicz
Copy link

UPDATE
Nulling the checkbox from within the viewmodel does not work. Threestate only works when you click directly on the checkbox. Nulling it from the viewmodel gives it a visual state like false. I have reproduced this directly in WPF.
image

            <CheckBox Content="Example CheckBox" 
                      IsThreeState="True" 
                      IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
            <Button Content="Toggle Check State"
                    Command="{Binding ToggleCheckStateCommand}"/>
        private void ToggleCheckState()
        {
            if (IsChecked == true)
                IsChecked = false;
            else if (IsChecked == false)
                IsChecked = null;
            else
                IsChecked = true;
        }

The same code for UNO. Null for bool? visually sets the checkbox to the value false.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants