简体   繁体   English

将 UWP VisualStateManager 与变量一起使用

[英]Using UWP VisualStateManager with varables

I can use VisualStateManager to change individual properties of controls.我可以使用VisualStateManager更改控件的各个属性。 Something like this:像这样的东西:

           <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <!--small window-->
                        <AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="Control1.FontSize" Value="13"/>
                        <Setter Target="Control2.FontSize" Value="13"/>
                        <Setter Target="Control3.FontSize" Value="13"/>
                        <Setter Target="Control4.FontSize" Value="13"/>
                    </VisualState.Setters>
                </VisualState>
                <VisualState>
                    <VisualState.StateTriggers>
                        <!--large window-->
                        <AdaptiveTrigger MinWindowHeight="665" MinWindowWidth="1000"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="Control1.FontSize" Value="24"/>
                        <Setter Target="Control2.FontSize" Value="24"/>
                        <Setter Target="Control3.FontSize" Value="24"/>
                        <Setter Target="Control4.FontSize" Value="24"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

This works but is soooo much typing!这有效,但打字太多!

Is it possible to use VisualStateManager to set a value for the font and than refer to this variable in XAML?是否可以使用VisualStateManager设置字体值而不是在 XAML 中引用此变量?

Something like this:像这样的东西:

          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <!--small window-->
                        <AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="@MyFontSize" Value="13"/>
                    </VisualState.Setters>
                </VisualState>
                <VisualState>
                    <VisualState.StateTriggers>
                        <!--large window-->
                        <AdaptiveTrigger MinWindowHeight="665" MinWindowWidth="1000"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="@MyFontSize" Value="24"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

I could then use @MyFontSize variable in XAML when designing controls and I could change it in one place.然后,我可以在设计控件时在 XAML 中使用@MyFontSize变量,并且可以在一处更改它。

<TextBlock x:Name="Control1" FontSize="@MyFontSize"/>
<TextBlock x:Name="Control2" FontSize="@MyFontSize"/>
<TextBlock x:Name="Control3" FontSize="@MyFontSize"/>

Is it possible to do something like this with UWP VisualStateManager ?是否可以使用 UWP VisualStateManager做这样的事情?

Is it possible to use VisualStateManager to set a value for the font and than refer to this variable in XAML是否可以使用 VisualStateManager 为字体设置值,而不是在 XAML 中引用此变量

I'm afraid you can't set variable within VisualStateManager , But for your scenario, we have a workaround that use Setting class as medium and effect other TextControl with MVVM bind.恐怕您无法在VisualStateManager设置变量,但是对于您的场景,我们有一种解决方法,即使用Setting类作为媒介并通过 MVVM 绑定影响其他 TextControl。

For example例如

public class Setting : INotifyPropertyChanged
{
    private double _fontSize = 10;
    public double CFontSize
    {
        get { return _fontSize; }
        set { _fontSize = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Usage用法

<Page.Resources>
    <local:Setting x:Key="Setting" />
</Page.Resources>
<StackPanel>
    <TextBlock
        x:Name="BaseControl"
        VerticalAlignment="Center"
        FontSize="{Binding CFontSize, Source={StaticResource Setting}, Mode=TwoWay}"
        Text="Hello" />
    <TextBlock
        x:Name="Control1"
        VerticalAlignment="Center"
        FontSize="{Binding CFontSize, Source={StaticResource Setting}, Mode=TwoWay}"
        Text="How are you" />
    <TextBlock
        x:Name="Control2"
        VerticalAlignment="Center"
        FontSize="{Binding CFontSize, Source={StaticResource Setting}, Mode=TwoWay}"
        Text="Fine thank you, and you?" />

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState>
                <VisualState.StateTriggers>
                    <!--  small window  -->
                    <AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="BaseControl.FontSize" Value="13" />
                </VisualState.Setters>
            </VisualState>
            <VisualState>
                <VisualState.StateTriggers>
                    <!--  large window  -->
                    <AdaptiveTrigger MinWindowHeight="665" MinWindowWidth="1000" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="BaseControl.FontSize" Value="24" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</StackPanel>

Found a similar but simpler way to do this inspired by @Nico Zhu's approach.受@Nico Zhu 方法的启发,找到了一种类似但更简单的方法。 Sharing here in case someone else finds it useful.在这里分享以防其他人发现它有用。

My approach is to use one control as a template and bind all other controls of that type to it.我的方法是使用一个控件作为模板并将该类型的所有其他控件绑定到它。

The VisualStateManager sets the property for the "master" controls: VisualStateManager设置“主”控件的属性:

  <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>

                <VisualState>
                    <VisualState.StateTriggers>
                        <!--VisualState to be triggered when window width is <665 effective pixels.-->

                        <AdaptiveTrigger MinWindowHeight="0" MinWindowWidth="0"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="txtHeader.FontSize" Value="13"/>
                        <Setter Target="txtRegular.FontSize" Value="10"/>
                    </VisualState.Setters>
                </VisualState>
                <VisualState>
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowHeight="665" MinWindowWidth="1000"/>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="txtHeader.FontSize" Value="20"/>
                        <Setter Target="txtRegular.FontSize" Value="16"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

All other controls can bind to "master" controls.所有其他控件都可以绑定到“主”控件。

<TextBlock Text="My Header 1" FontSize="{Binding ElementName=txtHeader, Path=FontSize}" />
<TextBlock Text="My Header 2" FontSize="{Binding ElementName=txtHeader, Path=FontSize}" />
<TextBlock Text="My regular text 1" FontSize="{Binding ElementName=txtRegular, Path=FontSize}" />
<TextBlock Text="My regular text 2" FontSize="{Binding ElementName=txtRegular, Path=FontSize}" />

When a user resizes page, VisualStateManager will change the master controls, all others will get it through binding.当用户调整页面大小时, VisualStateManager将更改主控件,所有其他控件都将通过绑定获取。

If you want to, you can create hidden controls just to server as templates.如果您愿意,您可以创建隐藏控件作为模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM