- Note-03

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zlxadhkust/article/details/51197557

Chapter 10: Resources

Resource Basics

The Resources Collection

Every element includes a Resources property, which is an instance of the ResourceDictionary class. The resources collection can hold any type of object, indexed by string.

Because every element has access to the resources in its own resource collection and the resources in all of its parents' resource collections.most common way to define resources is at the window level.

	<ImageBrush x:Key="TileBrush" />

The first attribute, named Key, assigns the name under which the resource object will be indexed in the Window.Resources collection.

To use a resource, there are two markup extensions that you can use:

static resources

Static resources are set once, when the window is first created.

You must always define a resource in your markup before you refer to it.

<Button Background="{StaticResource TileBrush}" />

dynamic resources

Dynamic resources are reapplied if the resource is changed.

The Hierarchy of Resources

Every element has its own resource collection, and WPF performs a recursive search up your element tree to find the resource you want. It uses the resource it finds first.

<Button Margin="5" Padding="5" FontWeight="Bold" FontSize="14">
		<ImageBrush x:Key="TileBrush" TileMode="Tile" ViewportUnits="Absolute" Viewport="0 0 10 10" ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>
		<StaticResource ResourceKey="TileBrush"/>
	<Button.Content>Another Tiled Button</Button.Content>

Static and Dynamic Resources

Whenever you change a brush in WPF, any controls that use that brush refresh themselves automatically. It doesn't matter whether they get their brushes through a resource.

The difference is that a static resource grabs the object from the resources collection once. Depending on the type of object (and the way it's used), any changes you make to that object may be noticed right away. However, the dynamic resource looks the object up in the resources collection every time it's needed. That means you could place an entirely new object under the same key, and the dynamic resource would pick up your change.

As a general guideline, use dynamic properties only when you have these conditions:

  • Your resource has properties that depend on system settings (such as the current Windows colors or fonts)
  • You plan to replace your resource objects programmatically

Nonshared Resources

Accessing Resources in Code

private void cmdChange_Click(object sender, RoutedEventArgs e)
	Button cmd = (Button)sender;
	ImageBrush brush = (ImageBrush)sender.FindResource("TileBrush");

Application Resources

Application resources give you a great way to reuse an object across your entire application.

System Resources

In the System.Windows namespace

  • SystemColors gives you access to color settings
  • SystemFonts gives you access to font settings
  • SystemParameters wraps a huge list of settings that describe the standard size of various screen elements, keyboard and mouse settings, and screen size, and whether various graphical effects are switched on.

The secret is a set of three classes named SystemColors, SystemFonts, and SystemParameters, all of which expose all their details through static properties.

Resource Dictionaries

If you want to share resources between multiple projects, you can create a resource dictionary.

Creating a Resource Dictionary

Using a Resource Dictionary

Sharing Resources Between Assemblies

You can use a Type object as a key name for a style. This tells WPF to apply the style to the appropriate type of element automatically.

Your resource dictionary must be in a file named generic.xaml, and that file must be placed in a Themes subfolder in your application. The resources in the generic.xaml files are considered part of the default theme, and they're always made available.

Chapter 11: Styles and Behaviors

Style Basics

Thanks to the property value inheritance feature, when you set these properties at the window level, all the elements inside the window will acquire the same values, unless they explicitly override them.

<Window xmlns:sys="clr-namespace:System;assembly=mscorlib" ... >

		<FontFamily x:Key="ButtonFontFamily">Times New Roman</FontFamily>
		<sys:Double x:Key="ButtonFontSize">18</s:Double>
		<FontWeight x:Key="ButtonFontWeight">Bold</FontWeight>

	<Button Padding="5" Margin="5" Name="cmd"
		FontFamily="{StaticResource ButtonFontFamily}"
		FontWeight="{StaticResource ButtonFontWeight}"
		FontSize="{StaticResource ButtonFontSize}">
			A Customized Button

Simplify it with style:

	<Style x:Key="BigFontButtonStyle">
		<Setter Property="Control.FontFamily" Value="Times New Roman" />
		<Setter Property="Control.FontSize" Value="18" />
		<Setter Property="Control.FontWeight" Value="Bold" />

That creates an object of System.Windows.Style.

Every WPF element can use a single style (or no style). The style plugs into an element through the element's Style property (which is defined in the base FrameworkElement class).

<Button Padding="5" Margin="5" Name="cmd" Style="{StaticResource BigFontButtonStyle}">
	A Customized Button

With C#

cmd.Style = (Style)cmd.FindResource("BigFontButtonStyle");

Styles set the initial appearance of an element, but you're free to override the characteristics they set.

Property Description

Creating a Style Object

You don't need to use styles and resources together. You could define the style of a particular button by filling its Style collection directly, as shown here:

<Button Padding="5" Margin="5">
			<Setter Property="Control.FontFamily" Value="Times New Roman" />
			<Setter Property="Control.FontSize" Value="18" />
			<Setter Property="Control.FontWeight" Value="Bold" />
	<Button.Content>A Customized Button</Button.Content>

Setting Properties

The only limitation is that a setter can only change a dependency property.

In some cases, you won't be able to set the property value using a simple attribute string.

<Style x:Key="HappyTiledElementStyle">
	<Setter Property="Control.Background">
			<ImageBrush TileMode="Tile" ViewportUnits="Absolute" Viewport="0 0 32 32" ImageSource="happyface.jpg" Opacity="0.3">

To identify the property you want to set, you need to supply both a class and a property name.

Notice the "Button.Xxx":

<Style x:Key="BigFontButtonStyle">
	<Setter Property="Button.FontFamily" Value="Times New Roman" />
	<Setter Property="Button.FontSize" Value="18" />
	<Setter Property="Button.FontWeight" Value="Bold" />

There are some cases in WPF where the same properties are defined in more than one place in the element hierarchy.Below code won't work:

<Style x:Key="BigFontStyle">
	<Setter Property="Button.FontFamily" Value="Times New Roman" />
	<Setter Property="Button.FontSize" Value="18" />
	<Setter Property="TextBlock.FontFamily" Value="Arial" />
	<Setter Property="TextBlock.FontSize" Value="10" />

<Style x:Key="BigFontButtonStyle" TargetType="Button">
	<Setter Property="FontFamily" Value="Times New Roman" />
	<Setter Property="FontSize" Value="18" />
	<Setter Property="FontWeight" Value="Bold" />

Attaching Event Handlers

<Style x:Key="MouseOverHighlightStyle">
	<EventSetter Event="TextBlock.MouseEnter" Handler="element_MouseEnter" />
	<EventSetter Event="TextBlock.MouseLeave" Handler="element_MouseLeave" />
	<Setter Property="TextBlock.Padding" Value="5"/>

private void element_MouseEnter(object sender, MouseEventArgs e)
	((TextBlock)sender).Background = new SolidColorBrush(Colors.LightGoldenrodYellow);

private void element_MouseLeave(object sender, MouseEventArgs e)
	((TextBlock)sender).Background = null;

<TextBlock Style="{StaticResource MouseOverHighlightStyle}">
	Hover over me.

MouseEnter and MouseLeave use direct event routing, which means they don't bubble up or tunnel down the element tree.

If you need the functionality shown here, you're more likely to use event triggers, which define the action you want declaratively (and so require no code).

Event setters aren't a good choice when handling an event that uses bubbling.

The Many Layers of Styles

In other cases, you might want to create a style that builds upon another style.

	<Style x:Key="BigFontButtonStyle">
		<Setter Property="Control.FontFamily" Value="Times New Roman" />
		<Setter Property="Control.FontSize" Value="18" />
		<Setter Property="Control.FontWeight" Value="Bold" />
	<Style x:Key="EmphasizedBigFontButtonStyle"
		BasedOn="{StaticResource BigFontButtonStyle}">
		<Setter Property="Control.Foreground" Value="White" />
		<Setter Property="Control.Background" Value="DarkBlue" />

You can use the BasedOn property to create an entire chain of inherited styles. The only rule is that if you set the same property twice, the last property setter (the one in the derived class furthest down the inheritance chain) overrides any earlier definitions.

Automatically Applying Styles by Type

You simply need to set the TargetType property to indicate the appropriate type (as described earlier) and leave out the key name altogether. When you do this, WPF actually sets the key name implicitly using the type markup extension, as shown here:

x:Key="{x:Type Button}"

Now the style is automatically applied to any buttons all the way down the element tree.

You can explicitly replaces the style, like:

<Button Padding="5" Margin="5" Style="{x:Null}">A Normal Button</Button>



Chapter 17: Control Templates

Understanding Logical Trees and Visual Trees

Understanding Templates

Creating Control Templates