UWP重用视觉状态管理器

时间:2020-01-15 11:03:02

标签: c# xaml uwp responsive visualstatemanager

为什么我们没有UWP这样容易响应的助手?

我在单独的.xaml文件中具有以下样式:

<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>

我有一个使用这些样式的页面(为简单起见,省略了大量代码):

<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>

现在,我可以给所有这些控件一个x:Name并在此页面中使用VisualStateManager来调整文本的大小,但是我在整个应用程序中都使用了这些文本样式,我想在以下位置进行更改一点,使用简单的类似于CSS的查询为不同的屏幕尺寸定义字体大小:

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

那么如何在VisualStateManager中使用ResourceDirectory来一次更改所有屏幕样式的文本样式?

我尝试使用this answer,但是根据我的评论,我无法成功,我尝试为<StackPanel>的其中一个应用较大的边距(也给它一个这样的名字),但没有任何改变。

1 个答案:

答案 0 :(得分:1)

在测试了您提供的内容(this answer)之后,我修改了一些代码:

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);
                }
            }
        }
    }
}

用法

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>

最诚挚的问候。