Adaptive Triggers in Resource Dictionary

爱⌒轻易说出口 提交于 2019-12-10 23:17:38

问题


I am trying to have a simple header of the page "adaptively" change the padding value based off of the width of the Page. Namely I have a header TextBlock using a style from a Resource Dictionary as shown below:

<Style x:Key="PageHeaderStyle" TargetType="TextBlock">
        <Setter Property="FontSize" Value="16" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="FontWeight" Value="Bold" />
</Style>

In my page now I have a simple TextBlock that uses the Style from the Resource Dictionary above. In the page if I use the following code my adaptive triggers as shown below everything works:

    <Page
...
        Style="{StaticResource PageStyle}">

        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup>
                    <VisualState x:Name="Narrow">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="0" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="PageHeader.Padding" Value="48,0,0,0" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Compact">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="720" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="PageHeader.Padding" Value="0,0,0,0" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Wide">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="1024"/>
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="PageHeader.Padding" Value="0,0,0,0" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Grid.RowDefinitions>
                <RowDefinition Height="{StaticResource GridHamburgerHeight}"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="14"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Border Background="{x:Bind Path=helper:CommonStyles.HamburgerPaneBackgroundColour}" Grid.Row="0" Grid.ColumnSpan="2"/>
            <TextBlock Style="{StaticResource PageHeaderStyle}" Grid.Column="1" Text="HOME"/>
        </Grid>
    </Page>

My question is, how can I move that Adaptive VisualStateManager piece into the Style object within the Resource Dictionary itself so that I can re-use this header style and its "adaptive-ness" without having to paste the VisualStateManager on each page.

Thanks!


回答1:


As I've tried it's not possible to change page's template, seems to always use a default one. Therefore, taking into account that VisualStateManager must be in the root element of a Control - source at MSDN:

Control authors or app developers add VisualStateGroup object elements to the root element of a control template definition in XAML, using the VisualStateManager.VisualStateGroups attached property.

you will probably have to create a custom UserControl or extend Page class - there you can add VisualStateManager and you won't have to repeat it all over, just use that control/page.


This is very simple example and should be extended, but it will give you a point to start (the source code you can check at Github. For your case I would create a TemplatedControl - right click on your project in solution manager, then Add->New Item, then select Templated Control, lets name it AdaptiveTriggerControl, this should create a cs file and a Generic.xaml in Themes folder. Open the AdaptiveTriggerControl.cs file and modify the class it derives from - change from Control to ContentControl:

public sealed class AdaptiveTriggerControl : ContentControl

In Generic.xaml you define the control:

<Style TargetType="local:AdaptiveTriggerControl" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:AdaptiveTriggerControl">
                <Border x:Name="MyBorder"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">
                    <!--Background="{TemplateBinding Background}"-->
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup>
                            <VisualState x:Name="Narrow">
                                <VisualState.StateTriggers>
                                    <AdaptiveTrigger MinWindowWidth="0" />
                                </VisualState.StateTriggers>
                                <VisualState.Setters>
                                    <Setter Target="MyBorder.Background" Value="Red"/>
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Compact">
                                <VisualState.StateTriggers>
                                    <AdaptiveTrigger MinWindowWidth="720" />
                                </VisualState.StateTriggers>
                                <VisualState.Setters>
                                    <Setter Target="MyBorder.Background" Value="Green"/>
                                </VisualState.Setters>
                            </VisualState>
                            <VisualState x:Name="Wide">
                                <VisualState.StateTriggers>
                                    <AdaptiveTrigger MinWindowWidth="1024"/>
                                </VisualState.StateTriggers>
                                <VisualState.Setters>
                                    <Setter Target="MyBorder.Background" Value="Blue"/>
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ContentPresenter Content="{TemplateBinding Content}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Then you can use it simply like this:

<local:AdaptiveTriggerControl>
    <TextBlock Text="Content of your page"/>
</local:AdaptiveTriggerControl>

More information about TemplatedControls, a sample of creating UserControl.



来源:https://stackoverflow.com/questions/42614367/adaptive-triggers-in-resource-dictionary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!