UWP/WinRT:如何使用 VisualState 触发器更改某种类型的所有控件的样式? [英] UWP/WinRT: How to use VisualState Triggers to change the styling of all controls of a certain type?

查看:95
本文介绍了UWP/WinRT:如何使用 VisualState 触发器更改某种类型的所有控件的样式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 UWP 应用中,我有一系列由 AppBarSeparators 分隔的 AppBarButtons.当窗口大小低于一定数量时,我想隐藏 AppBarSeparators 以节省空间.

In my UWP app, I have a series of AppBarButtons separated by AppBarSeparators. When the window size drops below a certain amount, I want to hide the AppBarSeparators to save space.

我尝试过类似的方法,但没有用:

I tried something like this, but it didn't work:

<VisualState.Setters>
   <Setter Target="AppBarSeparator" Value="Collapsed"/>
</VisualState.Setters>

我知道不可能给每个 AppBarSeparators 标签,所以我可以直接定位它们,因为它们是作为绑定的一部分动态生成的.

I understand it's not possible to give each of the AppBarSeparators labels so I can target them directly, because they are dynamically generated as part of a binding.

那么当我的窗口缩小到特定大小以下时,如何隐藏所有 AppBarSeparators?

So how can I hide all AppBarSeparators when my window shrinks below a certain size?

这是我的 XAML 的精简版本,用于显示 AppBarSeparators 是如何生成的:

Here is a stripped down version of my XAML to show how the AppBarSeparators are being generated:

<Pivot x:Name="docPivot"
       ItemsSource="{Binding}">

    <Pivot.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                </Grid.RowDefinitions>

                <StackPanel Orientation="Horizontal"
                            Grid.Row="0">
                    <AppBarButton/>
                    <AppBarSeparator/>
                    <AppBarButton/>
                    <AppBarButton/>
                    <AppBarSeparator/>
                </StackPanel>

                <StackPanel Orientation="Horizontal"
                            Grid.Row="1">
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Pivot.ItemTemplate>

</Pivot>

推荐答案

正如我们在评论中所讨论的,您的 AppBarSeparators 是在 PivotDataTemplate,当控件放在DateTemplate里面时,它们就变成了你的数据对象的可视化结构,但是VisualState针对的是控件,所以不能在这里工作.

As we've discussed in the comment, your AppBarSeparators are generated in the Pivot's DataTemplate, when controls are placed inside the DateTemplate, they becomes the visual structure of your data objects, but VisualState targets the controls, so can it not work here.

您可以将数据绑定与 Converter 来做这个,如果大小窗口在运行时是可变的,您可能还需要使用 INotifyPropertyChanged 接口.

You can use DataBinding with Converter to do this, and if the size of the window is changeable during the run-time, you may also need complete your data source class with INotifyPropertyChanged Interface.

例如这里:

<Page.Resources>
    <local:BoolVisibleConverter x:Key="cvt" />
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Pivot x:Name="docPivot" ItemsSource="{x:Bind pivotlist}" SizeChanged="docPivot_SizeChanged">
        <Pivot.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="auto" />
                    </Grid.RowDefinitions>
                    <StackPanel Orientation="Horizontal" Grid.Row="0">
                        <AppBarButton Icon="Accept" Label="Accept" />
                        <AppBarSeparator Visibility="{Binding WindowWidth, Converter={StaticResource cvt}}" />
                        <AppBarButton Icon="Cancel" Label="Cancel" />
                        <AppBarButton Icon="Add" Label="Add" />
                        <AppBarSeparator Visibility="{Binding WindowWidth, Converter={StaticResource cvt}}" />
                    </StackPanel>
                    <StackPanel Orientation="Horizontal"
                        Grid.Row="1">
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </Pivot.ItemTemplate>
    </Pivot>
</Grid>

背后的代码,我使用了 FrameworkElement.SizeChanged 事件 获取窗口的宽度运行时,如果您只想在第一次加载布局时使布局适合移动设备或 PC,则不需要此事件,也不需要 INotifyPropertyChanged:

Code behind, I used FrameworkElement.SizeChanged event to get the window's width during the run-time, if you just want to make the layout fit for mobile or PC at the first time the layout loading is, then this event is not needed, neither is the INotifyPropertyChanged:

private ObservableCollection<MyPivotItem> pivotlist = new ObservableCollection<MyPivotItem>();

public MainPage()
{
    this.InitializeComponent();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    pivotlist.Clear();
    pivotlist.Add(new MyPivotItem { });
    pivotlist.Add(new MyPivotItem { });
    pivotlist.Add(new MyPivotItem { });
    pivotlist.Add(new MyPivotItem { });
}

private void docPivot_SizeChanged(object sender, SizeChangedEventArgs e)
{
    foreach (var item in docPivot.Items)
    {
        var pivotitem = item as MyPivotItem;
        pivotitem.WindowWidth = Window.Current.Bounds.Width;
    }
}

MyPivotItem 类是这样的:

public class MyPivotItem : INotifyPropertyChanged
{
    public MyPivotItem()
    {
        _windowwidth = Window.Current.Bounds.Width;
    }

    private double _windowwidth;

    public double WindowWidth
    {
        get { return _windowwidth; }
        set
        {
            if (value != _windowwidth)
            {
                _windowwidth = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

BoolVisibleConverter 在这里非常简单:

public class BoolVisibleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        double? width = (double?)value;
        if (width <= 700)
            return Visibility.Collapsed;
        return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

这篇关于UWP/WinRT:如何使用 VisualState 触发器更改某种类型的所有控件的样式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆