gpt4 book ai didi

wpf - 如何跨 WPF 应用程序定义公共(public)资源(包括模板)?

转载 作者:行者123 更新时间:2023-12-04 20:44:09 25 4
gpt4 key购买 nike

我正在寻找一种方法来定义可从我的应用程序中的任何位置访问的 WPF 资源(目前,用作静态资源)。

我的资源在此资源字典中定义:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="flatButtonStyle" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" TargetType="{x:Type Button}">
<Setter Property="BorderThickness" Value="4"/>
</Style>
</ResourceDictionary>

this question 的选定答案表示我必须将该资源字典合并到我的 App.xaml 中。文件(一个名为 AppWideResources 的项目):
<Application x:Class="AppWideResources.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

起初,这似乎有效。此窗口中的按钮以带有超厚边框的扁平方式适本地设置样式:
<Window x:Class="AppWideResources.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AppWideResources" Height="300" Width="300"
>
<StackPanel>
<Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/>
</StackPanel>
</Window>

然而 ,一旦我在控制模板中使用我的共享资源,这将停止工作:

我的(出于这个问题的目的,非常简化)控制:
using System;
using System.Windows;
using System.Windows.Controls;

namespace AppWideResources
{
public class MyControl : Control
{
static MyControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
}
}
}

...和相应的 Themes\Generic.xaml文件:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AppWideResources">

<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource flatButtonStyle}" Content="1"/>
<Button Style="{StaticResource flatButtonStyle}" Content="2"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

</ResourceDictionary>

然后将此控件插入到我的窗口中:
<Window x:Class="AppWideResources.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AppWideResources"
Title="AppWideResources" Height="300" Width="300"
>
<StackPanel>
<Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/>
<local:MyControl/>
</StackPanel>
</Window>

如果我运行这个, XamlParseException 被抛出,说是静态资源 flatButtonStyle找不到。

我发现的唯一解决方法是将公共(public)资源字典显式合并到控件模板的本地资源字典中:
<ControlTemplate TargetType="local:MyControl">
<ControlTemplate.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ControlTemplate.Resources>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource flatButtonStyle}" Content="1"/>
<Button Style="{StaticResource flatButtonStyle}" Content="2"/>
</StackPanel>
</ControlTemplate>

然而,这不仅非常冗长且容易出错,有几行冗余代码(我的实际项目包含相当多的模板控件,而不仅仅是一个),我还担心通过多次加载静态资源而浪费系统资源(每次包含一次 CommonResources.xaml)。 (这种担心是否合理?或者 WPF 每次加载特定资源字典时是否使用相同的实例?)

所以,问题是: 使 WPF 资源在整个应用程序(包括控件模板)中可访问的正确方法是什么?

最佳答案

静态资源 将在应用程序实际运行之前加载 XAML 期间解析并分配给属性。所以,static resource has to be available at the time of loading .

它适用于普通按钮,因为资源查找一直持续到应用程序资源并从那里解决它。但是MyControl template still not loaded into app visual tree so it can't traverse upto application resources .

有两种方法可以实现:

  • 合并您已经实现的 Generic.xaml 中的 ResourceDictionary。
  • 其他方式是使用动态资源它在加载期间将一个 Expression 对象分配给该属性,但直到运行时要求该 Expression 对象提供值时才实际查找资源。这个defers looking up the resource until it is needed at runtime .

  • 在这里阅读 - StaticResource v/s DynamicResource .

    这将 无需在 Generic.xaml 中合并字典即可工作 :
    <Button Style="{DynamicResource flatButtonStyle}" Content="1"/>
    <Button Style="{DynamicResource flatButtonStyle}" Content="2"/>

    关于wpf - 如何跨 WPF 应用程序定义公共(public)资源(包括模板)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20824197/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com