从代码隐藏设置样式会使应用程序崩溃

Setting a Style from codebehind crashes the app

我有这个页面:

<Page
    x:Class="My.FilesPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:My"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:viewmodel="using:My.ViewModel" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    d:DataContext="{d:DesignInstance Type=viewmodel:FilesPageViewModel}"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Page.Resources>
        <Style TargetType="ListView" x:Name="ListStyle">
            <Setter Target="ItemContainerStyle">
                <Setter.Value>
                    <Style TargetType="ListViewItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    </Style>
                </Setter.Value>
            </Setter>
            <Setter Target="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <RelativePanel HorizontalAlignment="Stretch" Padding="0, 16">
                            <Image RelativePanel.AlignLeftWithPanel="True" 
                                                   Source="Assets/Files.png" 
                                                   Width="32" Margin="16, 0"
                                                   Name="FileThumb"/>
                            <StackPanel Orientation="Vertical" RelativePanel.RightOf="FileThumb">
                                <TextBlock Text="{Binding Name}"/>
                                <TextBlock Text="{Binding ModifiedDate}"/>
                            </StackPanel>
                            <Button RelativePanel.AlignRightWithPanel="True" Background="Transparent">
                                <Image Source="Assets/icon_Less.png" Width="16" VerticalAlignment="Center"/>
                            </Button>
                        </RelativePanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="ListView" x:Name="GridStyle">
            <Setter Target="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <controls:WrapPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Target="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical" Width="125" >
                            <Image Source="Assets/Files.png" Width="115"/>
                            <RelativePanel HorizontalAlignment="Stretch">
                                <TextBlock Text="{Binding Name}" RelativePanel.AlignLeftWithPanel="True" MaxWidth="96" TextWrapping="Wrap" HorizontalTextAlignment="Center"/>
                                <Button Background="Transparent" RelativePanel.AlignRightWithPanel="True">
                                    <Image Source="Assets/icon_Less.png" Width="16" VerticalAlignment="Center"/>
                                </Button>
                            </RelativePanel>
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Page.Resources>
    <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
            <ToggleButton Name="ViewStyleToggle"
                          IsChecked="False" Background="Transparent"
                          Checked="EnableGridStyle" Unchecked="EnableListStyle"
                          Content="Toggle"/>                
        <ListView Name="FileListView" ItemsSource="{Binding Files}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
                  Style="{StaticResource ListStyle}"/>
    </StackPanel>
</Page>

我在用户按下按钮时设置了 ListView 的样式,代码如下:

namespace My
{
    public sealed partial class FilesPage : Page
    {
        public FilesPage()
        {
            this.InitializeComponent();
        }

        public void EnableGridStyle(object sender, RoutedEventArgs e)
        {
            FileListView.Style = (Style)Resources["GridStyle"];
        }
        public void EnableListStyle(object sender, RoutedEventArgs e)
        {
            FileListView.Style = (Style)Resources["ListStyle"];
        }
    }
}

像这样更改样式会使应用程序崩溃,并且没有有意义的堆栈跟踪。我做错了什么?

使用x:Key,而不是x:Name,喜欢

<Style TargetType="ListView" x:Key="ListStyle">

通常我们使用键来查找用户定义的样式,而不是名称。

ListView默认使用的ItemsPanel模板是ItemsStackPanel,就是VirtualizingStackPanel。为了获得更高的性能,请使用 ItemsPanel 而不是您用作 GridStyle 的 ItemsPanel 模板的 WrapPanel,并将其 Orientation property 设置为 Horizo​​ntal。

既然你想要得到想要的包装行为,你可以使用 ItemsWrapGrid 作为 ItemsPaneltempalte 来实现这个效果,这也是 VirtualizingStackPanel。

同时WrapPanel不能UI虚拟化,可能会导致渲染等问题,所以可以参考下面的代码更改GridStyle.

<Style TargetType="ListView" x:Key="GridStyle">
            <Setter Target="ItemsPanel">
                <Setter.Value>
                  <ItemsPanelTemplate>
                    <ItemsWrapGrid Orientation="Horizontal"/>
                  </ItemsPanelTemplate>   
                </Setter.Value>
            </Setter>
……
</Style>

注意需要使用style的Key而不是Name来改变style(如x:Key="GridStyle") .