UWP re-use visual state manager

折月煮酒 提交于 2020-01-23 17:22:48

问题


Why don't we have such easy responsive helpers for UWP?

I have these styles in a separate .xaml file:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Project.App.WindowsApp.Styles">
    <Style x:Key="TextTitleH1" TargetType="TextBlock" >
        <Setter Property="FontFamily" Value="Quicksand"/>
        <Setter Property="FontWeight" Value="Light"/>
        <Setter Property="FontSize" Value="30" />
    </Style>
    <Style x:Key="TextTitleH2" TargetType="TextBlock" >
        <Setter Property="FontFamily" Value="Quicksand"/>
        <Setter Property="FontWeight" Value="Light"/>
        <Setter Property="FontSize" Value="24" />
    </Style>
    <Style x:Key="TextTitleH3" TargetType="TextBlock" >
        <Setter Property="FontFamily" Value="Quicksand"/>
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="FontSize" Value="22" />
    </Style>
    <Style x:Key="TextTitleH4" TargetType="TextBlock" >
        <Setter Property="FontFamily" Value="Quicksand"/>
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="FontSize" Value="16" />
    </Style>
    <Style x:Key="TextNormal" TargetType="TextBlock" >
        <Setter Property="FontFamily" Value="Quicksand"/>
        <Setter Property="FontWeight" Value="Light"/>
        <Setter Property="FontSize" Value="16" />
    </Style>
</ResourceDictionary>

I have a page using these styles (leaving out a lot of code for simplicity):

<ScrollViewer >
    <Grid>
       ...

        <StackPanel>
            <TextBlock  Text="{Binding Source={CustomResource Page_Dashboard_LatestImage}}" Style="{StaticResource TextTitleH4}" />
            ...
            <TextBlock Text="{CustomResource Page_Dashboard_NoImage}" Style="{StaticResource TextNormal}"/>

            <TextBlock Text="{CustomResource Page_Dashboard_LatestImage_Description}" Style="{StaticResource TextNormal}" />
         ...

        </StackPanel>
        <StackPanel>
            <TextBlock Text="{Binding Source={CustomResource Page_Dashboard_TipsTitle}} Style="{StaticResource TextTitleH4}" />
            ...
        </StackPanel>
     ...
    </Grid>
</ScrollViewer>

Now I could give all of those controls a x:Name and use VisualStateManager within this page to resize the text, but I am using these text styles throughout the entire app and I want to change them at one point, defining a fontsize for different screen sizes, using a simple css-like query:

@media only screen and (min-width: 600px) {
  .TextTileH1 {
    font-size: 36;
  }
}

So how can I generically use VisualStateManager within a ResourceDirectory to change all text styles at once for a different screen size?

I have tried using this answer, but as per my comment I was not able to succeed, I've tried to apply a bigger margin to one of the <StackPanel>'s (also giving it a name like it should) but nothing changed.


回答1:


After testing what you provided (this answer), I modified some code:

public class VisualStateExtensions : DependencyObject
{
    public static void SetVisualStatefromTemplate(UIElement element, DataTemplate value)
    {
        element.SetValue(VisualStatefromTemplateProperty, value);
    }

    public static DataTemplate GetVisualStatefromTemplate(UIElement element)
    {
        return (DataTemplate)element.GetValue(VisualStatefromTemplateProperty);
    }

    public static readonly DependencyProperty VisualStatefromTemplateProperty =
        DependencyProperty.RegisterAttached("VisualStatefromTemplate", typeof(DataTemplate), typeof(VisualStateExtensions), new PropertyMetadata(null,new PropertyChangedCallback(VisualStatefromTemplateChanged)));

    private static void VisualStatefromTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is FrameworkElement frameworkElement)
        {
            var visualStateGroups = VisualStateManager.GetVisualStateGroups(frameworkElement);
            if (visualStateGroups != null)
            {
                var template = (DataTemplate)e.NewValue;
                var content = (FrameworkElement)template.LoadContent();
                var groups = VisualStateManager.GetVisualStateGroups(content);
                if (groups!=null && groups.Count>0)
                {
                    var original = groups.First();
                    groups.Remove(original);
                    visualStateGroups.Add(original);
                }
            }
        }
    }
}

Usage

App.xaml

...
<DataTemplate x:Key="VisualStateTemplate">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup >
                <VisualState x:Name="NarrowView" >
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="0" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="Header.FontSize" Value="20" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="WideView">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="1000" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="Header.FontSize" Value="30" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</DataTemplate>
...

MainPage.xaml

<Grid controls:VisualStateExtensions.VisualStatefromTemplate="{StaticResource VisualStateTemplate}">
    <TextBlock x:Name="Header" Text="Hello World!"/>
</Grid>

Best regards.



来源:https://stackoverflow.com/questions/59750059/uwp-re-use-visual-state-manager

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