The following forum(s) have migrated to Microsoft Q&A (Preview): Developing Universal Windows apps!
Visit Microsoft Q&A (Preview) to post new questions.

Learn More

 locked
[UWP] VisualStateManager not reset to default state when using an UserControl with a DependencyProperty RRS feed

  • Question

  • Hi,

    please checkout my minimal code sample here to understand the issue better:

    https://github.com/AtosNicoS/DependencyPropertyVisualStateProblem

    I have a usercontrol with a boolean dependency property. This property is bind to a togglebutton in the Usercontrol itself. The idea of the Dependency Property is to read and set the button state from outside with a proper UWP/Xaml like abstraction (DependencyProperty).

    Then I introduce a visualstatemanager in the mainpage that uses my usercontrol. If I set a checkbox value to true the togglebutton should also reflect this change. That works so far. However the problem is, that if I uncheck that checkbox the visualstate goes into its default state, but the default dependency property (unchecked) is not triggered again.

    This bug does not appear when the togglebutton is only bound oneway, not twoway to the property. But in my usecase I need a twoway binding, so how should I implement this?

    Cheers

    Nico

    Monday, October 14, 2019 12:50 PM

All replies

  • Hi,

    I checked your demo, you probably shouldn't use VisualState here.

    You want to trigger the StateTrigger when the value of the CheckBox changes, so that the state of the UserControl is modified. But when StateTrigger.IsActive=False, the trigger stops and no longer interferes with the state of the control, which prevents you from returning the control to the default state.

    Depending on your situation, you can directly bind the CheckBox.IsChecked property.

    <StackPanel Orientation="Vertical">
        <CheckBox x:Name="TestCheckBox" Content="Checkbox"/>
        <local:MyUserControl1 IsButtonChecked="{x:Bind TestCheckBox.IsChecked.Value,Mode=OneWay}"
                              x:Name="MyUserControl1Test"/>
    </StackPanel>
    

    Best regards.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, October 15, 2019 1:19 AM
  • Hi Richasy,

    I thought that when IsActive is false the VisualStateManager return to the default state. Actually it does, because other properties also got reset, only this special property if its TwoWay bindet.

    I cannot directly bind to the Property, because the StateTrigger in my real world scenario depends on enum states, not a boolean. In that case I would require a special converter, which I want to avoid because all view states declared in the xaml is much better readable.

    <local:MediaCallControlPanel IsChatButtonChecked="{x:Bind EnumValue, Mode=OneWay, Converter={StaticResource TodoAddConverter}}"/>
    Is there no option to realise this with the VisualStateManager? It looks more to me like a bug, because it works if the Property is binded OneWay.

    Tuesday, October 15, 2019 6:29 AM
  • Hi,

    You can try use Binding to replace x:Bind.

    <ToggleButton IsChecked="{Binding IsButtonChecked,Mode=TwoWay}"
                  Content="ToggleButton" />
    

    When using Binding, please set the DataContext in the constructor of the UserControl.

    public MyUserControl1()
    {
        this.InitializeComponent();
        DataContext = this;
    }
    
    Best regards.



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, October 15, 2019 8:32 AM
  • This does only partly work. I can trigger the Checkbox and it now works in both directions. But if i trigger the togglebutton manually the checkbox state will be ignored unless the button is not toggled anymore. So still not real solution for me.
    Tuesday, October 15, 2019 11:48 AM
  • Hi,

    Can I understand you mean is that when the ToggleButton state changes, the state of the CheckBox will change as well?

    Best regards.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, October 16, 2019 6:31 AM
  • I think I understand the problem better than befor now. Look at this:

        <Grid>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup>
                    <VisualState>
                        <VisualState.StateTriggers>
                            <StateTrigger IsActive="{x:Bind TestCheckBox.IsChecked.Value, Mode=OneWay}" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="TestCheckBox2.IsChecked" Value="True"/>
                            <Setter Target="MyTextBlock.Text" Value="Triggered"/>
                            <Setter Target="MyTextBox.Text" Value="Triggered"/>
                            <Setter Target="MyUserControl1.IsButtonCheckedData" Value="True"/>
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
    
            </VisualStateManager.VisualStateGroups>
    
            <StackPanel Orientation="Vertical">
                <CheckBox x:Name="TestCheckBox" Content="Checkbox" />
                <CheckBox x:Name="TestCheckBox2" IsChecked="False" Content="Checkbox2" />
                <TextBlock x:Name="MyTextBlock" Text="Test"></TextBlock>
                <TextBox x:Name="MyTextBox" Text="Test"></TextBox>
                <local:MyUserControl1 x:Name="MyUserControl1" IsButtonCheckedData="False"></local:MyUserControl1>
            </StackPanel>
        </Grid>

    If I change the textbox text to something else, then trigger the visual state and go back to the"default" state the text is back to what you've entered and not "Test". Which means a button (Checkbox2) that was checked before will still have the checked state even after leaving the visualstate.

    Now with a twoway binding (x:Bind) inside the usercontrol the behavior becomes even more weird. If you check the checkbox it will trigger the visual state and toggle the button. If you uncheck the checkbox it will leave the visualstate. You might expect it to restore the original selected value, as the checkbox2 does. But it does not. If there is a twoway binding inside the control, the current state is kept.

    A normal binding (as you suggested) will work the same way as checkbox2 does.

    The only possible solution to me sounds to define all possible states, otherwise the state of an object cannot be 100% safe.

     I am not sure if that is a bug though, what do you think?
    Wednesday, October 16, 2019 9:18 AM
  • Hi,

    This is not a mistake, but a normal situation.

    When you define a control in XAML, you create an initial value instead of the default value.

    When your VisualState changing, the application caches the value of the current control and applies the new value to the control. When the VisualState is canceled, the value of the previous state is returned instead of being initialized.

    So, when VisualState does not meet the requirements, the control will return the value of the previous state instead of the initial value.

    Based on this, you can create a new VisualState that assigns values to the control when the CheckBox is unchecked.

    <VisualState>
        <VisualState.StateTriggers>
            <StateTrigger IsActive="{x:Bind TestCheckBox.IsChecked.Value.Equals(x:False), Mode=OneWay}" />
        </VisualState.StateTriggers>
        <VisualState.Setters>
            <Setter Target="TestCheckBox2.IsChecked" Value="False"/>
            <Setter Target="MyTextBlock.Text" Value="Test"/>
            <Setter Target="MyTextBox.Text" Value="Test"/>
            <Setter Target="MyUserControl1.IsButtonCheckedData" Value="False"/>
        </VisualState.Setters>
    </VisualState>
    

    Best regards.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, October 17, 2019 2:49 AM