WPF(资源)

1.资源介绍

之前讲过直接设置元素的样式,但是直接设置对于样式的共享没有什么帮助。样式可以放在资源中。在资源中,可以把样式赋予指定的元素,把一个样式赋予某一类型的所有元素,或者为该样式使用一个键。要把样式赋予某一个类型的所有元素,可使用Style的TargetType属性,指定x:Type标记扩展{x:Type Button},从而将样式赋予一个按钮。要定义需要引用的样式,必须设置x:Key:

<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Canvas Background="#FFCFC9C9">
        <Canvas.Resources>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Pink" />
                <Setter Property="FontSize" Value="12" />
            </Style>
            <Style x:Key="BtnStyle1" TargetType="Button">
                <Setter Property="Background" Value="Gold" />
                <Setter Property="Foreground" Value="Red" />
                <Setter Property="FontSize" Value="12" />
            </Style>
        </Canvas.Resources>
        <Button x:Name="btn1" Style="{StaticResource BtnStyle1}" Content="Button3" 
                Width="75" Canvas.Left="260" Canvas.Top="38" />
        <Button x:Name="btn2" Content="Button4" Width="75" Canvas.Left="380" Canvas.Top="38" />
    </Canvas>
</Window>
  • 没有指定Key的Style就表示默认的样式:也可以这样写 
<Style TargetType="Button">
    <Setter Property="Background" Value="Pink" />
    <Setter Property="FontSize" Value="12" />
</Style>
  • 若是在元素中设置了样式中同名称的属性,就会应用指定的设置,下例的Background显示为AliceBlue
<Button x:Name="btn1" Style="{StaticResource BtnStyle1}" Background="AliceBlue" 
Content="Button3" Width="75" Canvas.Left="260" Canvas.Top="38" />

2.Null样式

如果在资源中定义了默认样式,那如果想让一个Button什么样式都不使用怎么办?   将Style定义为{x:Null} 就不会应用任何样式了。

<Button x:Name="btn2" Style="{x:Null}" Content="Button4" Width="75" Canvas.Left="380" Canvas.Top="38" />

3.样式继承

样式提供了一种继承样式。一个样式可以基于另一个样式。继承之后,它使用该样式定义的所有设置,并且可以修改继承的设置和添加新的设置。设置样式的BasedOn属性定义继承的样式。

<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Canvas Background="#FFCFC9C9">
        <Canvas.Resources>
            <Style TargetType="Button">
                <Setter Property="Background" Value="Pink" />
                <Setter Property="FontSize" Value="12" />
            </Style>
            <Style x:Key="BtnStyle1" TargetType="Button">
                <Setter Property="Background" Value="Gold" />
                <Setter Property="Foreground" Value="Red" />
                <Setter Property="FontSize" Value="12" />
            </Style>
            <Style x:Key="BtnStyle2" TargetType="Button" BasedOn="{StaticResource BtnStyle1}">
                <Setter Property="Background">
                    <Setter.Value>
                        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                            <GradientStop Color="#FFF3F3F3" Offset="0" />
                            <GradientStop Color="#FF700909" Offset="0.638" />
                            <GradientStop Color="#FFCB9A9A" Offset="0.322" />
                            <GradientStop Color="#FFC54D4D" Offset="1" />
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
                <Setter Property="Foreground" Value="White" />
            </Style>
        </Canvas.Resources>
        <Button x:Name="btn1" Style="{StaticResource BtnStyle1}" Content="Button3" 
                Width="75" Canvas.Left="260" Canvas.Top="38" />
        <Button x:Name="btn2" Style="{StaticResource BtnStyle2}" Content="Button4" 
                Width="75" Canvas.Left="380" Canvas.Top="38" />
    </Canvas>
</Window>

4.样式多用

按照上述定义的样式只能用于某一个控件,而不能将这个样式应用于多个控件,我们可以利用控件的继承关系使一个样式应用于多个控件!

WPF中的控件继承关系分两种:

  1. 控件 ->  Control  ->  FrameworkElement
  2. 控件 ->  FrameworkElement 

对于继承了Control的控件可以设置同样的样式:

<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Canvas Background="#FFCFC9C9">
        <Canvas.Resources>
            <Style x:Key="CtrStyle" TargetType="{x:Type Control}">
                <Setter Property="Background" Value="Pink" />
                <Setter Property="FontSize" Value="8" />
            </Style>
            <Style x:Key="BtnStyle" TargetType="Button" BasedOn="{StaticResource CtrStyle}">
                <Setter Property="Foreground" Value="White" />
            </Style>
        </Canvas.Resources>
        <Button Style="{StaticResource BtnStyle}" Content="Button" Width="75" Canvas.Left="38" Canvas.Top="38" />
        <Button Style="{StaticResource CtrStyle}" Content="Button" Width="75" Canvas.Left="90" Canvas.Top="73" />
        <Label Style="{StaticResource CtrStyle}" Content="Label" Canvas.Left="210" Canvas.Top="100" />
        <TextBox Style="{StaticResource CtrStyle}" Height="23" TextWrapping="Wrap" Text="TextBox" Width="120" />
        <TextBlock TextWrapping="Wrap" Text="TextBlock" Canvas.Left="60" Canvas.Top="115" />
    </Canvas>
</Window>
  • 这里的Button、Label、TextBox都继承了Control,就可以对它们设置Control中含有的属性值。而TextBlock没有继承Control,对其设置样式就会报错。 
  • 必须先定义父类的样式才能应用BasedOn继承

 5.动态资源

  • 上述用到的资源都是静态资源,定义的资源必须写在第一个元素之前,否则运行后会提示未找到资源,设计期间没有问题。但是应用的是动态资源可以在所有元素之前或之后
  • 通过StaticResource标记扩展,在加载期间搜索资源。如果在运行程序的过程中改变了资源,就应使用DynamicResource标记扩展。
  • DynamicResource需要的性能资源比StaticResource更多,因为其资源总数在需要时加载。只有需要在运行期间进行修改,才给资源使用DynamicResource。
  • DynamicResource若没有找到,也不会报错,会自动应用默认的样式。
  • BasedOn属性设置的资源只能是StaticResource

通过代码更换资源: 

<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Canvas x:Name="canvas1" Background="#FFCFC9C9" Margin="0,0,0,100" Width="500" Height="76">
        <Canvas.Resources>
            <Style x:Key="BtnStyle2" TargetType="Button">
                <Setter Property="Background" Value="Gold" />
                <EventSetter Event="Click" Handler="Button_Click3" />
            </Style>
            <Style x:Key="BtnStyle3" TargetType="Button">
                <Setter Property="Background" Value="Aqua" />
                <EventSetter Event="Click" Handler="Button_Click4" />
            </Style>
        </Canvas.Resources>
        <Button Style="{StaticResource BtnStyle2}" Content="Static" Width="75" Canvas.Left="145" Canvas.Top="13" />
        <Button Style="{DynamicResource BtnStyle2}" Content="Dynamic" Width="75" Canvas.Left="250" Canvas.Top="15" />
    </Canvas>
</Window>
private void Button_Click3(object sender, RoutedEventArgs e)
{
    Control ctr = sender as Control;
    ctr.Style = ctr.FindResource("BtnStyle3") as Style;
}

 从XAML中可以看出,两个Button都应用了BtnStyle2样式,所以都有了Button_Click3事件。当点击按钮后将样式更改为BtnStyle3,这个时候按钮就会应用BtnStyle3样式。注意点就是由于这里的事件是在样式中定义的,若是样式改变后,样式中的事件也会取消订阅,若是新样式中也有同样的事件,就会重新订阅新样式中的事件。这里点击按钮就会取消Button_Click3事件,订阅Button_Click4事件。

通过代码更改样式设置: 

<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Canvas x:Name="canvas1" Background="#FFCFC9C9" Margin="0,0,0,100" Width="500" Height="76">
        <Canvas.Resources>
            <Style x:Key="BtnStyle2" TargetType="Button">
                <Setter Property="Background" Value="Gold" />
                <EventSetter Event="Click" Handler="Button_Click3" />
            </Style>
            <Style x:Key="BtnStyle3" TargetType="Button">
                <Setter Property="Background" Value="Aqua" />
                <EventSetter Event="Click" Handler="Button_Click4" />
            </Style>
        </Canvas.Resources>
        <Button Style="{StaticResource BtnStyle2}" Content="Static" Width="75" Canvas.Left="145" Canvas.Top="13" />
        <Button Style="{DynamicResource BtnStyle2}" Content="Dynamic" Width="75" Canvas.Left="250" Canvas.Top="15" />
        <Button Click="Button_Click5" Content="Alter" Width="75" Canvas.Left="360" Canvas.Top="13" />
    </Canvas>
</Window>

添加一个按钮用于修改样式,事件Button_Click5。

private void Button_Click5(object sender, RoutedEventArgs e)
{
    Style resource = this.canvas1.Resources["BtnStyle2"] as Style;
    Setter setter = resource.Setters.OfType<Setter>().
                    LastOrDefault(s => s.Property == Button.BackgroundProperty);
    setter.Value = new SolidColorBrush(Colors.Blue);
}

 若是以上图代码修改,你会发现提示异常:System.InvalidOperationException:“使用“SetterBase”之后(密封),无法对其进行修改。”。所以样式在XAML中定义好以后就不能修改了,但是我们可以先移除这个样式,再添加一个同名的样式以达到修改样式的结果。

private void Button_Click5(object sender, RoutedEventArgs e)
{
    Style style = new Style(typeof(Button));
    style.Setters.Add(new Setter(Button.BackgroundProperty, new SolidColorBrush(Colors.Blue)));
    this.canvas1.Resources.Remove("BtnStyle2");
    this.canvas1.Resources.Add("BtnStyle2", style);
}

用上述代码可以达到修改样式的效果,但是修改后你会发现只有是动态资源的Button的背景色改变了,而用静态资源的Button并没有改变,所以这就是静态资源和动态资源的区别。定义用静态资源样式的控件,运行后就不能通更改样式达到改变效果的目的,但是我们可以直接修改你要修改的属性值。

6.作用域 

通过上述的例子,有没有发现资源都是定义的 Canvas.Resources。Resources是在FrameworkElement类里面,按道理是所有的控件都可以定义资源,并且资源只能定义一次。

//
// 摘要:
//     获取或设置本地定义的资源字典。
//
// 返回结果:
//     资源中当前本地定义的字典,其中的每个资源均可通过键进行访问。
[Ambient]
public ResourceDictionary Resources { get; set; }
<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <Style x:Key="BtnStyle2" TargetType="{x:Type Button}">
            <Setter Property="Background" Value="Aqua" />
        </Style>
    </Window.Resources>
    <Canvas x:Name="canvas1" Background="#FFCFC9C9" Margin="0,0,0,100" Width="500" Height="76">
        <Canvas.Resources>
            <Style x:Key="BtnStyle2" TargetType="Button">
                <Setter Property="Background" Value="Gold" />
            </Style>
        </Canvas.Resources>
        <Button x:Name="btn1" Style="{StaticResource BtnStyle2}" Content="Static" 
                Width="75" Canvas.Left="145" Canvas.Top="13" />
        <Button x:Name="btn2" Style="{StaticResource BtnStyle2}" Width="75" 
                Canvas.Left="250" Canvas.Top="15">
            <Button.Resources>
                <Style x:Key="BtnStyle2" TargetType="Button">
                    <Setter Property="Background" Value="Red" />
                </Style>
            </Button.Resources>
            <Button x:Name="btn3" Style="{StaticResource BtnStyle2}" Content="Button" />
        </Button>
    </Canvas>
</Window>

上述事例中,定义了三个同名的样式(BtnStyle2),但是在不同的资源中,那各个Button会应用哪个样式呢???

  • 若都是静态资源:btn1是Gold;btn2是Gold;btn3是Red;   静态资源是根据当前元素往上离它最近的资源为主。
  • 若都是动态资源:btn1是Gold;btn2是Red;btn3是Red;    动态资源是根据所属关系最近的为主。
  • 资源按层次结构搜索,各资源只能在自己所属范围内有效,不在该范围内的元素应用了该资源会提示错误。

     如果需要将同一个样式应用于多个窗口,就可以用应用程序定义样式。App.xaml文件以定义应用程序的全局资源。应用程序样式对其中的每个窗口都有效;每个元素都可以访问该资源。在窗口中,如果该元素未在该窗口中找到资源,就可以通过Application继续搜索资源。

<Application x:Class="WpfAppLearn1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfAppLearn1" StartupUri="Window3.xaml">
    <Application.Resources>
        <Style x:Key="AppBtnStyle">
            <Setter Property="Button.Background" Value="Gainsboro" />
            <Setter Property="Button.Foreground" Value="White" />
            <Setter Property="Button.FontSize" Value="15" />
        </Style>
    </Application.Resources>
</Application>

7.资源字典

如果相同的资源可用于不同的应用程序,把资源放在一个资源字典中就比较有效。使用资源字典,可以在多个应用程序之间共享文件,也可以把资源字典放在一个程序集中,供应用程序共享。

要共享程序集中的资源字典,应创建一个库。可以把资源字典文件添加到程序集中。这个文件的构建动作必须设置为Resource,从而把它作为资源添加到程序集中。


添加新建项《资源字典》,命名为  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:WpfAppLearn1">
    <Style TargetType="Button">
        <Setter Property="Background" Value="ForestGreen" />
        <Setter Property="FontSize" Value="18" />
    </Style>
    <Style x:Key="ButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="Magenta" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="FontSize" Value="12" />
    </Style>
    <Style x:Key="ButtonStyle2" TargetType="Button" BasedOn="{StaticResource ButtonStyle}">
        <Setter Property="Foreground" Value="Green" />
    </Style>
</ResourceDictionary>

对于目标窗体,需要引用这个库,并把资源字典添加到这个字典中。通过ResourceDictionary的MergedDictionaries属性,可以使用添加进来的多个资源字典文件。 使用ResourceDictionary的Source属性,可以引用字典。在引用时,使用包URI语法。包URI语法可以指定为绝对的,其中URI以"pack://"开头,也可以指定为相对的,如下例所示。使用相对语法,包含字典的引用程序集WpfAppLearn1跟在"/"的后面,其后是";component"。component表示,该字典作为程序集中的一个资源包含在内。之后添加字典文件的名称 Dictionary.xaml。如果把字典添加到子文件夹中,则还必须声明子文件夹名。

<Window x:Class="WpfAppLearn1.Window3" 
        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:WpfAppLearn1" 
        mc:Ignorable="d" Title="Window3" Height="206" Width="509" WindowStartupLocation="CenterScreen">
    <Canvas x:Name="canvas1" Background="#FFCFC9C9" Margin="0,0,0,100" Width="500" Height="76">
        <Canvas.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="/WpfAppLearn1;component/Dictionary1.xaml" />
                </ResourceDictionary.MergedDictionaries>
                <Style x:Key="BtnStyle1" TargetType="Button">
                    <Setter Property="Background" Value="Lavender" />
                </Style>
            </ResourceDictionary>
        </Canvas.Resources>
        <Button x:Name="btn0" Width="75" Canvas.Left="250" Canvas.Top="15" Content="Button0" />
        <Button Style="{StaticResource BtnStyle1}" Content="Static" Width="75" Canvas.Left="55" Canvas.Top="23" />
        <Button x:Name="btn1" Style="{StaticResource ButtonStyle2}" Content="Static" Width="75" Canvas.Left="135" Canvas.Top="43" />
        <Button x:Name="btn2" Style="{StaticResource ButtonStyle}" Width="75" Canvas.Left="360" Canvas.Top="17">
            <Button.Resources>
                <Style x:Key="BtnStyle2" TargetType="Button">
                    <Setter Property="Background" Value="Red" />
                </Style>
            </Button.Resources>
            <Button x:Name="btn3" Style="{StaticResource BtnStyle2}" Content="Button" />
        </Button>
    </Canvas>
</Window>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bridge_go

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

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

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

打赏作者

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

抵扣说明:

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

余额充值