Использование UWP VisualStateManager с переменными значениями

#xaml #uwp #visualstatemanager

#xaml #uwp #visualstatemanager

Вопрос:

Я могу использовать VisualStateManager для изменения отдельных свойств элементов управления. Что-то вроде этого:

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

Это работает, но тааак много печатать!

Можно ли использовать VisualStateManager для установки значения для шрифта, а затем ссылаться на эту переменную в XAML?

Что-то вроде этого:

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

Затем я мог бы использовать @MyFontSize переменную в XAML при разработке элементов управления, и я мог бы изменить ее в одном месте.

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

Возможно ли сделать что-то подобное с UWP VisualStateManager ?

Ответ №1:

Можно ли использовать VisualStateManager для установки значения для шрифта, а затем ссылаться на эту переменную в XAML

Боюсь, вы не можете установить переменную внутри VisualStateManager , но для вашего сценария у нас есть обходной путь, который использует Setting class в качестве среды и использует другой TextControl с привязкой MVVM.

Например

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

Использование

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

Комментарии:

1. Отличный трюк! Таким образом, вы устанавливаете свойство с помощью VisualSateManager для одного элемента управления, а все остальные наследуют от него. Спасибо!

Ответ №2:

Нашел аналогичный, но более простой способ сделать это, вдохновленный подходом @ Nico Zhu. Делюсь здесь на случай, если кто-то другой сочтет это полезным.

Мой подход заключается в использовании одного элемента управления в качестве шаблона и привязке к нему всех других элементов управления этого типа.

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>
  

Все остальные элементы управления могут привязываться к «основным» элементам управления.

 <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}" />
  

Когда пользователь изменяет размер страницы, VisualStateManager изменяет основные элементы управления, все остальные получат его через привязку.

Если вы хотите, вы можете создавать скрытые элементы управления только для сервера в качестве шаблонов.