【问题标题】:UWP re-use visual state managerUWP 重用视觉状态管理器
【发布时间】:2020-05-02 03:21:49
【问题描述】:

为什么我们没有这样简单的 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;
  }
}

那么我一般如何在ResourceDirectory 中使用VisualStateManager 来一次更改所有文本样式以适应不同的屏幕尺寸?

我尝试过使用this answer,但根据我的评论我无法成功,我尝试为&lt;StackPanel&gt; 之一应用更大的边距(也给它一个应该的名字) 但没有任何改变。

【问题讨论】:

    标签: c# xaml uwp responsive visualstatemanager


    【解决方案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>
    

    最好的问候。

    【讨论】:

    • 感谢这些修改,注意到if 条件之一也不正确。但不幸的是,它不会改变文本字体大小,我想我遗漏了一些东西,但出于测试目的,我做了同样的事情。 controls: 是指VisualStateExtensions 的命名空间吗?它是在Grid 上还是(在我的情况下)在ScrollViewer 上是否重要?为了确保我检查了VisualStateManager 本身在粘贴到ScrollViewer 内(Grid 之外)时是否正常工作。
    • 是的,controls: 是命名空间引用。我建议把这个VisualStateExtensions.VisualStatefromTemplate 放在根元素上。例如,如果您的GridScrollViewer 中,则将此扩展名写在ScrollViewer
    • 不幸的是,这似乎仍然没有改变与字体相关的任何内容。您是否在测试项目中测试过您的代码?
    • 是的,我测试了它,它运行良好。您在Grid 中的内容是否与VisualStateGroup 中的内容相对应?比如VisualStateGroup中,我设置了一个VisualStateTarget为Header.FontSize,同时必须有一个TextBlock,实际名称为Header。如果您的代码仍然无法正常工作,请发布完整代码以供我们分析。
    • 啊,现在可以了!虽然这不是最好的解决方案,因为我需要在任何地方添加x:Name,但只需添加大量x:Name="TextTitleH1_1"x:Name="TextTitleH1_2" 等并在数据模板中也包含这些内容会更容易一些。因此,在有人找到更好的解决方案之前,我会将其标记为已接受...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多