Search code examples
c#xamluwpwin-universal-app

UWP respond to Control width change


I want my control to respond to its width change instead of the Window width change. Can I achieve that using VisualStateManager or pure xaml?

One possible solution I can think of is using DataTriggerBehavior. For example:

<Interactivity:Interaction.Behaviors>
    <Interactions:DataTriggerBehavior Binding="{Binding Width, ElementName=PlaylistDataTemplateControl}" ComparisonCondition="Equal" Value="1000">
        <Interactions:ChangePropertyAction TargetObject="{Binding ElementName=AlbumTextBlock}" PropertyName="Visibility" Value="Collapsed"/>
    </Interactions:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>

I put it in the PlaylistDataTemplateControl but nothing happens when width changes.


Solution

  • The default trigger for UWP is only about the window. If you want to implement triggering on the control, there are two ways. The first is to listen for the SizeChanged event, and the second is to write the trigger yourself.

    Here is the first case:

    xaml

    <StackPanel>
    
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="Narrow">
                    <VisualState.Setters>
                        <Setter Target="MyControl.Background" Value="White"/>
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Width">
                    <VisualState.Setters>
                        <Setter Target="MyControl.Background" Value="Blue"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    
        <ContentControl x:Name="MyControl" Width="200" Height="100" SizeChanged="MyControl_SizeChanged"/>
    
        <Button Content="Change Width" x:Name="WidthButton" Click="WidthButton_Click"/>
    </StackPanel>
    

    xaml.cs

    private void MyControl_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (e.NewSize.Width == 200)
        {
            VisualStateManager.GoToState(this, "Narrow", true);
        }
        else
        {
            VisualStateManager.GoToState(this, "Width", true);
        }
    }
    
    private void WidthButton_Click(object sender, RoutedEventArgs e)
    {
        MyControl.Width = MyControl.Width == 300 ? 200 : 300;
    }
    

    This is just a simple example. First define the VisualState of the control in XAML, then change the state of the control in the SizeChanged event, which can achieve your purpose.

    If you are interested in custom triggers, you can refer to this Microsoft-provided example, which has a trigger on Control Size.

    Best regrads.