首页 > 解决方案 > 指定(或未指定)键时的模板加载行为不同

问题描述

我发现根据您为 a 设置 Style 的方式FrameworkElement,程序可能会崩溃,也可能不会崩溃。这是说明问题的代码:

StyleTemplates.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:tabcontrolgrey">
    <Style TargetType="FrameworkElement">
        <Setter Property="Margin" Value="5" />
    </Style>

    <Style TargetType="GroupBox" BasedOn="{StaticResource {x:Type FrameworkElement}}">
        <Setter Property="BorderBrush" Value="Green" />
        <Setter Property="BorderThickness" Value="2" />

    </Style>

    <Style TargetType="GroupBox" x:Key="SecondGB" BasedOn="{StaticResource {x:Type FrameworkElement}}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="1" />

    </Style>
</ResourceDictionary>

ResourceDictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:tabcontrolgrey">


    <DataTemplate DataType="{x:Type local:ItemExt1}">
        <ContentControl Content="{Binding Variables}" />
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:GroupOfVariables}">
        <GroupBox Header="{Binding Label}" Style="{StaticResource SecondGB}"/>
    </DataTemplate>
</ResourceDictionary>

MainWindow.xaml

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:tabcontrolgrey"
        x:Class="tabcontrolgrey.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="StyleTemplates.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <TabControl ItemsSource="{Binding ItemLists}"
        TabStripPlacement="Left">
        <TabControl.ItemContainerStyle>
            <Style TargetType="TabItem">
                <Setter Property="Header" Value="{Binding Header}" />
                <Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        DataContext = new MainWindowVM();
    }
}

以下是数据和 VM 类:

 public class MainWindowVM
    {


        public ObservableCollection<object> ItemLists => new ObservableCollection<object>()
        {
            new ItemExt1(),
        };

    }

public class ItemExt1
{
    public string Header => "Item 1";
    public bool IsEnabled => true;
    public GroupOfVariables Variables { get; }
    public ItemExt1()
    {
        Variables = new GroupOfVariables();
    }
}


public class GroupOfVariables
{
    public string Label => "Label";
}

如果你运行上面的程序,当你点击选项卡控件时,程序会因为SecondGB找不到样式而崩溃。

现在,在 中ResourceDictionary.xaml,使用默认样式而不设置对 的引用SecondGB,即:

<DataTemplate DataType="{x:Type local:GroupOfVariables}">
        <GroupBox Header="{Binding Label}"/>
</DataTemplate>

你会发现程序可以运行,并且中定义的样式StyleTemplates.xaml应用正确!换句话说,根据你是否FrameworkElement通过键名来引用一个 's Style,加载顺序不同,程序行为不同。这可能会导致混乱。

为什么会这样?它在任何地方都有记录吗?

标签: c#wpf

解决方案


Key引用的StaticResource:

<DataTemplate DataType="{x:Type local:GroupOfVariables}">
    <GroupBox Header="{Binding Label}" Style="{StaticResource SecondGB}"/>
</DataTemplate>

应该在编译时解决。它是静态资源实现

SecondGB在“StyleTemplates.xaml”中定义,但未在“ResourceDictionary.xaml”中加载,因此找不到命名资源。对于 StaticResource,它会导致运行时异常(设计时 Visual Studio 应该"{StaticResource }"在 xaml-editor 中强调使用情况)

默认样式在运行时应用,因为在 MainWindow 中加载 GroupBox 时,已经加载了默认 GroupBox 样式。

DynamicResources在运行时解析。即使 DynamicResource 未解析,应用程序也不会崩溃。它也可以在视觉树的任何级别上被覆盖。

<DataTemplate DataType="{x:Type local:GroupOfVariables}">
    <GroupBox Header="{Binding Label}" Style="{DynamicResource SecondGB}"/>
</DataTemplate>

推荐阅读