UWP – Close a Flyout MVVM way with UWP XamlBehaviors

Datetime:2016-08-23 01:25:51          Topic: MVVM Model           Share

Using a Flyout control in an UWP app is super handy to show contextual actions, but somehow they aren’t very MVVM friendly.It was easier during windows 8.1 days, but with UWP it’s a hassle.

I’ve seen many solutions on how to tackle this problem, but let you give me mine just to show some other angles.

I’m trying to use the new UWP XamlBehaviors that went Open Source a while back, for all the info take a look here https://github.com/Microsoft/XamlBehaviors .

So the setup, we have a page that has a button – that button will open a flyout. On this flyout we have another button that will trigger some long running process in MVVM ( it’s not in this demo :stuck_out_tongue: ).What we want to do is dismiss the flyout from our MVVM if the process is done.

Here is the XAML code

C#

<Button x:Name="FlyoutButton"
        Margin="0,0,0,50"
        Content="Look ma I'm going to open a flyout"
        RelativePanel.AlignBottomWithPanel="True"
        RelativePanel.AlignHorizontalCenterWithPanel="True" Background="#FFBFBFBF">
    <Button.Flyout>
        <Flyout Placement="Full">
            <Grid Background="DarkGoldenrod" RequestedTheme="Dark">
                <RelativePanel>
                    <Button Content="Perform super long business logic code"
                            Command="{Binding LongCodeCommand}"
                            Margin="0,0,0,50"
                            RelativePanel.AlignBottomWithPanel="True"
                            RelativePanel.AlignHorizontalCenterWithPanel="True"/>
                </RelativePanel>
            </Grid>

            <interactivity:Interaction.Behaviors>
                <core:DataTriggerBehavior Binding="{Binding IsFlyoutClosed}"
                                            ComparisonCondition="Equal" Value="True">
                    <actions:CloseFlyoutAction />
                </core:DataTriggerBehavior>
            </interactivity:Interaction.Behaviors>
        </Flyout>
    </Button.Flyout>
</Button>
<Button x:Name="FlyoutButton"
        Margin="0,0,0,50"
        Content="Look ma I'm going to open a flyout"
        RelativePanel.AlignBottomWithPanel="True"
        RelativePanel.AlignHorizontalCenterWithPanel="True" Background="#FFBFBFBF">
    <Button.Flyout>
        <FlyoutPlacement="Full">
            <GridBackground="DarkGoldenrod" RequestedTheme="Dark">
                <RelativePanel>
                    <ButtonContent="Perform super long business logic code"
                            Command="{Binding LongCodeCommand}"
                            Margin="0,0,0,50"
                            RelativePanel.AlignBottomWithPanel="True"
                            RelativePanel.AlignHorizontalCenterWithPanel="True"/>
                </RelativePanel>
            </Grid>
 
            <interactivity:Interaction.Behaviors>
                <core:DataTriggerBehaviorBinding="{Binding IsFlyoutClosed}"
                                            ComparisonCondition="Equal" Value="True">
                    <actions:CloseFlyoutAction />
                </core:DataTriggerBehavior>
            </interactivity:Interaction.Behaviors>
        </Flyout>
    </Button.Flyout>
</Button>

Some things to note… We are using a MVVM command through binding for the button that is shown on the flyout.

The other thing, is the DataTriggerBehavior! It’s one of the behavior types that is available through the XamlBehaviors and what it allows us to do is perform some action when some data element changes to a certain value.

Here we are monitoring the IsFlyoutClosed boolean of our MVVM ViewModel to see when it’s being set to True. If this happens, we’ll perform an action called CloseFlyoutAction.

This action is a custom one and it’s purpose is to close the current given Flyout, as shown in the code below.

C#

public class CloseFlyoutAction : DependencyObject, IAction
{
    public object Execute(object sender, object parameter)
    {
        var flyout = sender as Flyout;
        flyout?.Hide();

        return null;
    }
}
public class CloseFlyoutAction : DependencyObject, IAction
{
    public object Execute(object sender, object parameter)
    {
        var flyout = senderas Flyout;
        flyout?.Hide();
 
        return null;
    }
}

And that’s it… only thing left to do is manipulate the boolean on the ViewModel when you want to close the flyout.

C#

public bool IsFlyoutClosed
{
    get { return _isFlyoutClosed; }
    set
    {
        Set(() => IsFlyoutClosed, ref _isFlyoutClosed, value);
        if (value)
            IsFlyoutClosed = false;
    }
}
public bool IsFlyoutClosed
{
    get { return _isFlyoutClosed; }
    set
    {
        Set(() => IsFlyoutClosed, ref _isFlyoutClosed, value);
        if (value)
            IsFlyoutClosed = false;
    }
}

As always an example project is available on GitHub here… https://github.com/Depechie/UWPFlyoutCloseMVVM





About List