Ahmar
Ahmar

Reputation: 750

Content Control and Button Flyout

I am making a UWP app and I have come across a problem. I want to make a StackPanel which hosts two ComboBoxes and one TextBox. I can show it in the app if I create it inside the Grid and it works as expected. But for smaller screen devices I want to show a Button in place of the StackPanel and move the StackPanel to the button flyout.

I have tried to add the StackPanel to a ContentControl and then set it as the Flyout but it doesn't work. Flyout needs a FlyoutPresenter control to be able to show the flyout.

I don't want to create multiple StackPanel controls because of the naming collisions, but I do want it simple so I need to make changes to one side of the controls and when the user switches the screen or the view the smaller screen also shows the same stuff.

Can someone help me here? Maybe just point me in the right direction so I can figure it out on my own. Any help will be appreciated. Thanks

StackPanel control:

    <StackPanel Orientation="Vertical"
                x:Name="PageOptionsPanel"
                HorizontalAlignment="Right">
            <AppBarButton Label="Refresh"
                    Icon="Refresh"
                    Tapped="PageOptions_Tapped"/>
            <RelativePanel Margin="10,0">
                <TextBlock Text="Sort by:"
                        Name="SortText"
                        RelativePanel.AlignVerticalCenterWithPanel="True"
                        Margin="0,0,5,0"/>
                <ComboBox RelativePanel.RightOf="SortText"
                        x:Name="MSortingBox"
                        ItemsSource="{Binding EnSortList}"
                        RelativePanel.AlignVerticalCenterWithPanel="True"
                        SelectionChanged="MSortingBox_SelectionChanged"
                        Width="120"/>
            </RelativePanel>
            <RelativePanel Margin="10,0">
                <TextBlock Text="Country: "
                        Name="CountryText"
                        RelativePanel.AlignVerticalCenterWithPanel="True"
                        Margin="0,0,5,0"/>
                <ComboBox RelativePanel.RightOf="CountryText"
                        x:Name="MCountryBox"
                        ItemsSource="{Binding EnCountryList}"
                        RelativePanel.AlignVerticalCenterWithPanel="True"
                        SelectionChanged="MCountryBox_SelectionChanged"
                        Width="120"/>
            </RelativePanel>
        </StackPanel>

Flyout control:

    <Button>
        <Button.Flyout>
            <Flyout Placement="Left"
                    x:Name="MOptionsFlyout"
                    Content="{StaticResource PageOptionsFlyout}"
                    Opened="MOptionsFlyout_Opened">
            </Flyout>
        </Button.Flyout>
    </Button>

Upvotes: 1

Views: 752

Answers (2)

Pedro Silva
Pedro Silva

Reputation: 717

If I understand your question correctly, you want to share the XAML for your Options layout between the main page and a flyout, based on the size of the page (for phone vs tablet). You can do this by creating a DataTemplate with the layout and adding it to the page's resource dictionary. Then it can be referenced in multiple places.

Here's the code below that does that. It also hides and shows the pieces based on adaptive triggers.

<Page.Resources>
    <DataTemplate x:Key="PageOptionsTemplate">
        <StackPanel 
                    x:Name="PageOptionsPanel"
                    HorizontalAlignment="Right"
                    Orientation="Vertical">
            <AppBarButton
                        Icon="Refresh"
                        Label="Refresh" />
            <RelativePanel Margin="10,0">
                <TextBlock
                            Name="SortText"
                            Margin="0,0,5,0"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            Text="Sort by:" />
                <ComboBox
                            x:Name="MSortingBox"
                            Width="120"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            RelativePanel.RightOf="SortText"/>
            </RelativePanel>
            <RelativePanel Margin="10,0">
                <TextBlock
                            Name="CountryText"
                            Margin="0,0,5,0"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            Text="Country: " />
                <ComboBox
                            x:Name="MCountryBox"
                            Width="120"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            RelativePanel.RightOf="CountryText"
                             />
            </RelativePanel>
        </StackPanel>
    </DataTemplate>
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button Name="OptionsFlyoutButton" Content="Show Me" Visibility="Collapsed">
        <Button.Flyout>
            <Flyout>
                <ContentControl ContentTemplate="{StaticResource PageOptionsTemplate}"/>
            </Flyout>
        </Button.Flyout>
    </Button>
    <ContentControl Name="OptionsInLine" Visibility="Visible" ContentTemplate="{StaticResource PageOptionsTemplate}" />

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState>
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="320"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="OptionsInLine.Visibility" Value="Collapsed"/>
                    <Setter Target="OptionsFlyoutButton.Visibility" Value="Visible"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState>
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="720"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                </VisualState.Setters>
            </VisualState>
            <VisualState>
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="1024"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>

You can also move the DataTemplate out to the application level ResourceDictionary, so that it can be shared between multiple pages.

Finally, another option is to create a user control (using the uwp item template) for this. I recommend creating that if you needed more control over the layout, wanted to encapsulate the logic too, and share it across multiple apps.

For your example, the shared DataTemplate is the easiest path.

Upvotes: 3

MrCSharp
MrCSharp

Reputation: 1143

Just do this:

<Button Content="Show Me">
        <Button.Flyout>
            <Flyout>
                <StackPanel
                    x:Name="PageOptionsPanel"
                    HorizontalAlignment="Right"
                    Orientation="Vertical">
                    <AppBarButton
                        Icon="Refresh"
                        Label="Refresh" />
                    <RelativePanel Margin="10,0">
                        <TextBlock
                            Name="SortText"
                            Margin="0,0,5,0"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            Text="Sort by:" />
                        <ComboBox
                            x:Name="MSortingBox"
                            Width="120"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            RelativePanel.RightOf="SortText"/>
                    </RelativePanel>
                    <RelativePanel Margin="10,0">
                        <TextBlock
                            Name="CountryText"
                            Margin="0,0,5,0"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            Text="Country: " />
                        <ComboBox
                            x:Name="MCountryBox"
                            Width="120"
                            RelativePanel.AlignVerticalCenterWithPanel="True"
                            RelativePanel.RightOf="CountryText"
                             />
                    </RelativePanel>
                </StackPanel>
            </Flyout>
        </Button.Flyout>
    </Button>

to get this: enter image description here

When using the you get an auto display flyout that is shown whenever a user clicks the button, no code needed.

but to add content to that flyout, you need to have another element in it, then the stackpanel goes into it.

Hope this helps you.

Upvotes: 0

Related Questions