WPF getting started tutorial Series 12-dependency attributes (2), wpf getting started tutorial
Ii. Priority of dependency attributes
Since WPF allows us to set the value of the dependency attribute in multiple places, we must use a standard to ensure the priority of the value. For example, in the following example, if we set the button background color in three places, which setting will be the final result? Is it Black, Red or Azure?
<Window x:Class="WpfApp1.WindowDepend" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WindowDepend" Height="400" Width="400"> <Grid> <Button x:Name="myButton" Background="Azure"> <Button.Style> <Style TargetType="{x:Type Button}"> <Setter Property="Background" Value="Black"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="Red" /> </Trigger> </Style.Triggers> </Style> </Button.Style> Click </Button> </Grid></Window>
Based on the previous introduction, we learned about simple dependency attributes. Each time a dependency attribute is accessed, it processes the value from high to bottom in the following order. For details, see
Due to the idealization of This flowchart, we will encounter various problems in the actual work process, and I will not be able to solve them all, so we will not be able to thoroughly clarify these problems, so when we encounter problems, we will analyze them carefully to find out the reasons, and continue to summarize and draw inferences from each other.
Iii. Inheritance of dependency attributes
Property Value inheritance is a function of the Windows Presentation Foundation (WPF) attribute system. Property Value inheritance allows the child element in the element tree to obtain the value of a specific property from the parent element and inherit the value, as if it was set at any location in the nearest parent element. The parent element can also obtain its value through property value inheritance. Therefore, the system may recursively go to the page root element. Property Value inheritance is not the default behavior of the Property System. Attributes must be created with specific metadata settings so that the property can start property value inheritance for child elements.
The original intention of inheriting dependency attributes is that the settings of parent elements are automatically passed to child elements of all layers, that is, elements can inherit the value of dependency attributes from their parent level in the tree. We have a lot of contact in programming. For example, when we modify the font settings of the form parent container control, all levels of child controls will automatically use the font settings (provided that the child control has not been customized ). Next, let's take a practical example. The Code is as follows:
<Window x: Class = "WpfApp1.WindowInherited" xmlns =" http://schemas.microsoft.com/winfx/2006/xaml /Presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "Title =" WindowInherited "Height =" 400 "Width =" 500 "Loaded =" Window_Loaded "> <Grid. rowDefinitions> <RowDefinition Height = "101 *"/> <RowDefinition Height = "80"/> <RowDefinition Height = "80"/> </Grid. rowDefinitions> <StackPanel Grid. row = "0"> <Label Content = "FontSize inherited from Window"/> <TextBlock Name = "textBlockInherited" Text = "overwrites the inheritance, no FontSize inherited from Window "FontSize =" 36 "TextWrapping =" WrapWithOverflow "/> <StatusBar> NO FontSize inherited from Window, statusbar </StatusBar> </StackPanel> <WrapPanel Grid. row = "1"> <Label Content = "form font size"/> <ComboBox Name = "drpWinFontSize"> </ComboBox> <Button Name = "btnFontSize" Click = "btnFontSize_Click "> change the font of the window </Button> </WrapPanel> <WrapPanel Grid. row = "2"> <Label Content = "text font size"/> <ComboBox Name = "drpTxtFontSize"> </ComboBox> <Button Name = "btnTextBlock" Click = "btnTextBlock_Click "> change the TextBlock font </Button> </WrapPanel> </Grid> </Window>
Code
Using System; using System. collections. generic; using System. linq; using System. text; using System. threading. tasks; using System. windows; using System. windows. controls; using System. windows. data; using System. windows. documents; using System. windows. input; using System. windows. media; using System. windows. media. imaging; using System. windows. shapes; namespace WpfApp1 {/// <summary> /// WindowInherited. interaction logic of xaml // </summary> public partial class implements winherited: Window {public writable winherited () {InitializeComponent ();} private void btnFontSize_Click (object sender, RoutedEventArgs e) {this. fontSize = Convert. toInt32 (drpWinFontSize. text);} private void btnTextBlock_Click (object sender, RoutedEventArgs e) {this. textBlockInherited. fontSize = Convert. toInt32 (drpTxtFontSize. text);} private void Window_Loaded (object sender, RoutedEventArgs e) {List <int> listFontSize = new List <int> (); for (int I = 0; I <= 60; I ++) {listFontSize. add (I + 4);} drpTxtFontSize. itemsSource = listFontSize; drpWinFontSize. itemsSource = listFontSize ;}}}
As follows:
Window. the FontSize setting affects the font size of all internal elements. This is the so-called property value inheritance. For example, the first Label in the code above does not define FontSize, so it inherits the Window. fontSize value. However, once the child element provides explicit settings, this inheritance will be interrupted. For example, the second TextBlock defines its own FontSize, so the inherited value will no longer work.
At this time, you will find a very strange problem: Although StatusBar does not overwrite FontSize, it is also a child element of Window, but its font size has not changed, keeping the default value of the system. So what is the reason? As a beginner, I may wonder why there are different tables and tables. The official saying is that this is the principle? In fact, after careful research, we found that not all elements support property value inheritance. There will also be some unexpected situations, which are due to the following two aspects:
1. Some Dependency attributes specify Inherits as non-inheritance when registering, so that the inheritance will become invalid.
2. You have set this value for other higher priority settings. You can see the specific priority level in the "priority of dependency attributes" described earlier.
Property values are inherited through the hybrid tree operation. The parent object that holds the original value and the sub-object that inherits the value must both be a FrameworkElement or FrameworkContentElement, and both must belong to a logical tree. However, for existing WPF attributes that support property inheritance, property value inheritance can be permanently stored through mediation objects not in the logic tree. This applies to the following situations: Make the template element use all the inherited attribute values set on the instance where the template is applied, you can also use all the inherited property values set in a higher level page-level component (so they are also in a higher position in the logic tree. To make the inheritance of property values consistent in these two cases, the inheritance property must be registered as an additional property.
The reason is that some controls such as StatusBar, Tooptip, and Menu internally set their font attribute values to match the current system. In this way, you can use the control panel of the operating system to modify their appearance. This method has a problem: StatusBar intercepts attributes inherited from the parent element and does not affect its child elements. For example, if a Button is added to StatusBar. The font property of the Button is not changed because of the truncation of StatusBar, and its default value is retained. Therefore, you should pay special attention to these issues when using them.