WPF(资源调用)

资源初步认识https://blog.csdn.net/breakbridge/article/details/116271634

一、资源键 

大多少时候我们定义一个资源都是将其Key设置为一个字符串,但有时候我们也可以将Key设置为 ComponentResourceKey 对象。

<Application x:Class="WpfAppResource1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfAppResource1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="appSolid1" Color="Green" />
            <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="#666" />
        </ResourceDictionary>
    </Application.Resources>
</Application>

二、获取资源 

 这里只讲诉全局的资源,元素的资源同理。

1.Application.Current

  •  获取字符串作为Key的资源:
//获取资源
var rs2 = Application.Current.Resources["appSolid1"];
  •  获取ComponentResourceKey作为Key的资源:
ComponentResourceKey resourceKey = new ComponentResourceKey(typeof(MainWindow), "coldWaterBrush");
//获取资源
var rs1 = Application.Current.Resources[resourceKey];

2.FrameworkElement.FindResource 

  •   获取字符串作为Key的资源:
//获取资源
var rs3 = this.FindResource("appSolid1");
  •  获取ComponentResourceKey作为Key的资源:
ComponentResourceKey resourceKey = new ComponentResourceKey(typeof(MainWindow), "coldWaterBrush");
//获取资源
var rs3 = this.FindResource(resourceKey);

PS:这里不能用 this.Resources["appSolid1"]; 这只能获取该元素自身的资源 

三、修改资源 

修改资源自能对对应的资源字典赋值,不能是修改资源的值。

var rs2 = Application.Current.Resources["appSolid1"];
//rs2 = new LinearGradientBrush(Colors.Red, Colors.Green, 45.0);  //无效
//(rs2 as SolidColorBrush).Color = Colors.Red;   //会提示异常
Application.Current.Resources["appSolid1"] = new LinearGradientBrush(Colors.Red, Colors.Green, 45.0);

直接对rs2赋值是无效的, 

四、同Key资源 

当存在两个Key相同的资源时,会应用哪一个呢?

1.Dictionary.xaml 与 App.xaml

在同一个资源文件里有两个同样Key的资源会提示异常,当同样Key的资源在两个文件里面时是不会出现异常的。 

<!--  Dictionary1.xaml  -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:local="clr-namespace:WpfAppResource1">
    <SolidColorBrush x:Key="appSolid1" Color="Red" />
    <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="#FF5FA7FD" />
</ResourceDictionary>

<!--  App.xaml  -->
<Application x:Class="WpfAppResource1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfAppResource1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/WpfAppResource1;component/Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <SolidColorBrush x:Key="appSolid1" Color="Green" />
            <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="#666" />
        </ResourceDictionary>
    </Application.Resources>
</Application>

 当应用Key为appSolid1的资源时,是显示Green还是Red呢?

测试可知,会显示Green,这表示优先应用非资源字典里面的样式。 (不是因为Green样式在Red样式后面,放在前面也是一样)

2.Dictionary.xaml 与 Dictionary.xaml

若是将其放在另一个资源文件里面时:

<!--  Dictionary2.xaml  -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:local="clr-namespace:WpfAppResource1">
    <SolidColorBrush x:Key="appSolid1" Color="Green" />
    <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="#666" />
</ResourceDictionary>

<!--  App.xaml  -->
<Application x:Class="WpfAppResource1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfAppResource1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/WpfAppResource1;component/Dictionary2.xaml"/>
                <ResourceDictionary Source="/WpfAppResource1;component/Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

同名的会应用最后定义的资源文件,这里就会应用Dictionary1中的样式。 若是在Dictionary2中调用appSolid1样式时,也是调用的Dictionary1中的appSolid1样式。

3.App.xaml 与 Themes.Generic.xaml 

当在App.xaml 和 generic.xaml 中应用了同样的样式,会优先应用App.xaml中的 

PS: generic.xaml 中的样式不能通过上述的方法获取和修改资源。

五、两个Key的区别

 假设有两个资源字典:

<!--  Dictionary1.xaml  -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:local="clr-namespace:WpfAppResource1">
    <SolidColorBrush x:Key="appSolid1" Color="Red" />
    <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="Blue" />
</ResourceDictionary>

<!--  Dictionary2.xaml  -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:local="clr-namespace:WpfAppResource1">
    <Style TargetType="Button">
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="Background" Value="{StaticResource appSolid1}"/>
        <Setter Property="Foreground" Value="{StaticResource {ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}}"/>
    </Style>
</ResourceDictionary>

<!--  App.xaml  -->
<Application x:Class="WpfAppResource1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfAppResource1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/WpfAppResource1;component/Dictionary2.xaml"/>
                <ResourceDictionary Source="/WpfAppResource1;component/Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

这里应用的是StaticResource,若是 DynamicResource这里看不出区别。因为应用的是StaticResource,若是key都是字符串类型时,需先定义Dictionary1。若是我们先定义Dictionary2会怎样呢???

 应用字符串作为Key的资源会提示找不到,而ComponentResourceKey的资源是可以应用的。

六、访问其他程序集中的资源 

1.资源字典 

 现有程序集 WpfAppResource1,其中有资源 Dictionary1.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:local="clr-namespace:WpfAppResource1">
    <SolidColorBrush x:Key="appSolid1" Color="Red" />
    <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="Blue" />
</ResourceDictionary>

当我们需在  WpfAppResource2 中访问 WpfAppResource1 中的 Dictionary1.xaml 时,只需引用该资源即可:

<Application x:Class="WpfAppResource2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfAppResource2"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/WpfAppResource1;component/Dictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

PS:当 WpfAppResource2 作为主窗体启动时, WpfAppResource1 的 App.xaml 是无效的,即在该文件中定义的所有样式都不起作用。

2. Generic.xaml

当我们自定义控件时,静态构造函数中调用DefaultStyleKeyProperty.OverrideMetadata()方法时,就会在Generic.xaml中获取默认样式。

当我们在WpfAppResource1自定义一个控件,如下:

namespace WpfAppResource1
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    using System.Windows;

    public class Btn : Button
    {
        static Btn()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Btn), new FrameworkPropertyMetadata(typeof(Btn)));
        }
    }
}
<!--  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:WpfAppResource1">
    <Style TargetType="local:Btn">
        <Setter Property="FontSize" Value="20" />
        <Setter Property="Background" Value="Red" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Background="{TemplateBinding Background}" CornerRadius="20">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

这时我们就可以在  WpfAppResource2 中访问Btn了。若是我们在 WpfAppResource2 的Generic.xaml中也定义一个上述一样的Btn的样式,这是无效的,就算 WpfAppResource1中没有定义Btn的样式也不行,所以在哪创建了自定义控件就只能在哪个程序集的Generic中定义默认样式

这里再次说明一下两个Key的区别:

当WpfAppResource1的Generic.xaml如下时,我们可以在WpfAppResource2中直接访问ComponentResourceKey 定义的样式,而用字符串作为key就不行。

<!--  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:WpfAppResource1">
    <SolidColorBrush x:Key="appSolid1" Color="Red" />
    <SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MainWindow}, ResourceId=coldWaterBrush}" Color="Blue" />
</ResourceDictionary>

七、XML名称空间 

using System.Windows.Markup;

[assembly: XmlnsDefinition("http://schemas.bridge.com/WpfAppResource1/", "WpfAppResource1")]
[assembly: XmlnsPrefix("http://schemas.bridge.com/WpfAppResource1/", "custom")]
namespace WpfAppResource1
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    using System.Windows;
    public class Btn : Button
    {
        static Btn()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Btn), new FrameworkPropertyMetadata(typeof(Btn)));
        }
    }
}
  • XmlnsDefinition:指定 XAML 命名空间与 CLR 命名空间之间按程序集进行的映射,然后 XAML 对象编写器或 XAML 架构上下文使用后一种命名空间进行类型解析。
  •  XmlnsPrefix:当在 XAML 文件(序列化)中编写元素和特性时,或与具有 XAML 编辑功能的设计环境进行交互时,标识要与 XAML 命名空间关联用于 XAML 的推荐前缀。

我们可以给程序集定义一个访问的链接,这个链接只有在其他程序集中才可以使用,这时我们在 WpfAppResource2中调用Btn时,可以这么写:

<Window x:Class="WpfAppResource2.MainWindow" Title="MainWindow" 
        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:WpfAppResource2"
        xmlns:custom="http://schemas.bridge.com/WpfAppResource1/" 
        Width="800" Height="450" mc:Ignorable="d">
    <Grid>
        <custom:Btn Content="888"/>
    </Grid>
</Window>

 还可以更直接一点:

using System.Windows.Markup;

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "WpfAppResource1")]
namespace WpfAppResource1
{
    using System.Windows.Controls;
    using System.Windows;
    public class Btn : Button
    {
        static Btn()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Btn), new FrameworkPropertyMetadata(typeof(Btn)));
        }
    }
}
<Window x:Class="WpfAppResource2.MainWindow" Title="MainWindow" 
        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:WpfAppResource2"
        Width="800" Height="450" mc:Ignorable="d">
    <Grid>
        <Btn Content="888"/>
    </Grid>
</Window>

因为"http://schemas.microsoft.com/winfx/2006/xaml/presentation" 是所用XAML中默认的名称空间。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bridge_go

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值