【问题标题】:How to use VisualState AdaptiveTrigger to change ListView Item FontSize如何使用 VisualState AdaptiveTrigger 改变 ListView Item FontSize
【发布时间】:2017-11-28 19:51:35
【问题描述】:

我正在使用视觉状态自适应触发器来根据有效的屏幕分辨率更改页面外观。这很好用,但我不能让它为 ListView 项目工作。

我的 ListView 看起来像这样:

<ListView x:Name="listView" >
    <ListView.ItemTemplate>
        <DataTemplate>
                <TextBlock FontSize="20" Text="{Binding MyItem}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

我可以在 XAML 中静态更改 TextBlock 字体大小。但我不知道如何在 VisualState setter 目标中引用它。作为自动生成的孩子,我不能给 TextBlock 一个名字。我的视觉状态代码如下。我放了???我想在哪里引用 ListView TextBlock 项 FontSize。

 <VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
            <VisualState x:Name="NormalStateReadView">
                    <!-- VisualState to be triggered when window width is <720 effective pixels -->
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="0" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="???" Value="20" />
                    </VisualState.Setters>
                </VisualState>
    </VisualStateGroup>

    <VisualStateGroup>
            <VisualState x:Name="NormalStateReadView">
                    <!-- VisualState to be triggered when window width is >=720 effective pixels -->
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="720" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="???" Value="30" />
                    </VisualState.Setters>
                </VisualState>
    </VisualStateGroup>

任何帮助表示赞赏。

【问题讨论】:

  • 我可以在Grid中设置TextBlock的字体大小

标签: c# xaml uwp windows-10-universal


【解决方案1】:

您需要将模板包装在UserControl 中,以便自适应触发器起作用;视觉状态也应该进入模板内部,并确保它位于UserControl 的第一个直接子级(即Grid)之下。我看到您已经定义了两个视觉状态组,但实际上您只需要一个。

<ListView.ItemTemplate>
    <DataTemplate>
        <UserControl>
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup>
                        <VisualState x:Name="NarrowState">
                            <VisualState.StateTriggers>
                                <AdaptiveTrigger MinWindowWidth="0" />
                            </VisualState.StateTriggers>

                            <VisualState.Setters>
                                <Setter Target="Title.(TextBlock.FontSize)" Value="24" />
                            </VisualState.Setters>
                        </VisualState>

                        <VisualState x:Name="WideState">
                            <VisualState.StateTriggers>
                                <AdaptiveTrigger MinWindowWidth="720" />
                            </VisualState.StateTriggers>

                            <VisualState.Setters>
                                <Setter Target="Title.(TextBlock.FontSize)" Value="36" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>

                <TextBlock x:Name="Title" Text="{Binding Property1}" />
            </Grid>
        </UserControl>
    </DataTemplate>
</ListView.ItemTemplate>

更新

这是我认为更灵活的解决方案。它需要一些代码来设置,但结果是你得到了干净、可重用和可读的代码。

我们的想法是获取顶级VisualStateGroup 的引用,该引用定义在ListView 之外,主要在Page 级别。

然后,创建三个VisualStates(即普通)并将它们附加到一个新的VisualStateGroup应该属于UserControl 的第一个孩子。

一旦我们引用了这两个VisualStateGroups,我们就可以监控顶层的CurrentStateChanged,并相应地更新第二个的状态。

上面的所有逻辑都可以用Behavior 包裹在UWP XAML Behavior nuget package 中。

Behavior 到位后,您可以像这样简单地定义您的内部状态 -

<DataTemplate>
    <UserControl>
        <Interactivity:Interaction.Behaviors>
            <local:VisualStateInTemplateBehavior ParentVisualStateGroup="{Binding ElementName=AdaptiveVisualStates}">
                <local:VisualStateInTemplateBehavior.NarrowState>
                    <VisualState x:Name="Narrow">
                        <VisualState.Setters>
                            <Setter Target="Title.(TextBlock.FontSize)" Value="24" />
                        </VisualState.Setters>
                    </VisualState>
                </local:VisualStateInTemplateBehavior.NarrowState>

                <local:VisualStateInTemplateBehavior.NormalState>
                    <VisualState x:Name="Normal">
                        <VisualState.Setters>
                            <Setter Target="Title.(TextBlock.FontSize)" Value="32" />
                        </VisualState.Setters>
                    </VisualState>
                </local:VisualStateInTemplateBehavior.NormalState>

                <local:VisualStateInTemplateBehavior.WideState>
                    <VisualState x:Name="Wide">
                        <VisualState.Setters>
                            <Setter Target="Title.(TextBlock.FontSize)" Value="40" />
                        </VisualState.Setters>
                    </VisualState>
                </local:VisualStateInTemplateBehavior.WideState>
            </local:VisualStateInTemplateBehavior>
        </Interactivity:Interaction.Behaviors>

工作演示


随时查看工作示例here

【讨论】:

  • 嗨,谢谢。我接受了第一个解决方案。我更喜欢为页面定义视觉状态并在一个地方调整所有内容。
  • (或)我们可以使用BindableValueHolder
【解决方案2】:

我们不能将AdaptiveTrigger 用于DataTemplate 内的元素。您应该使用UserControl 来执行此操作。这个answer 可以帮助你。如果您想要video tutorial,那么此视频可能会对您有所帮助。但我有一些解决方法。

这是我的方法:

  1. DataTemplate之外创建TextBlock并设置Visibility="Collapsed"

    <TextBlock Name="SetFontSize" Visibility="Collapsed"/>
    

    注意:您也可以使用BindableValueHolder 代替它,并使用AdaptiveTrigger 设置它的Value 属性。

    <helpers:BindableValueHolder x:Name="SetFontSize"/>
    
  2. 使用AdaptiveTrigger 更改此TextBlockFontSize

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="NormalStateReadView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="SetFontSize.FontSize" Value="20" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    
        <VisualStateGroup>
            <VisualState x:Name="WideStateReadView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="720" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="SetFontSize.FontSize" Value="30" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    
  3. DataTemplateTextBlockFontSize数据绑定到外TextBlock

    <TextBlock FontSize="{Binding Path=FontSize, ElementName=SetFontSize}"/>
    

这是您的代码:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState x:Name="NormalStateReadView">
            <!-- VisualState to be triggered when window width is <720 effective pixels -->
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="0" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="SetFontSize.FontSize" Value="20" />
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>

    <VisualStateGroup>
        <VisualState x:Name="WideStateReadView">
            <!-- VisualState to be triggered when window width is >=720 effective pixels -->
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="720" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="SetFontSize.FontSize" Value="30" />
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<TextBlock Name="SetFontSize" Visibility="Collapsed"/>
<ListView x:Name="listView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock FontSize="{Binding Path=FontSize, ElementName=SetFontSize}" Text="{Binding MyItem}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

【讨论】:

  • 非常漂亮和优雅的解决方案。非常感谢!
  • 我不得不说,这对我来说有点 hacky。 :) 但我尊重 OP 给出的理由。
  • @JustinXL 一开始我喜欢拥有所有的 VisualStateManager。
  • 但是如果您需要修改的不仅仅是字体大小怎么办?我认为我们都需要一个更好的解决方案。
  • @JustinXL 我们可以将ResourceDictionary 修改为AdaptiveTrigger 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 2011-09-29
  • 2019-09-18
  • 1970-01-01
相关资源
最近更新 更多