2, Priority of dependent properties
Because WPF allows us to set the values of dependent properties in multiple places, we have to use a standard to guarantee the priority of values. For example, in the following example, we set the background color of the button 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>
Through the previous brief introduction, we learned about simple dependency properties. Each time we access a dependency property, it will internally process the value from the high to the bottom in the following order. See the figure below for details
Due to the idealization of this flow chart, we will encounter all kinds of problems in the actual work process, and I can't meet them all, and I can't completely explain these problems. Therefore, when we encounter problems, we will carefully analyze them, find out the reasons, and constantly summarize and draw inferences from one example.
3, Inheritance of dependent properties
Property value inheritance is a feature of the Windows Presentation Foundation (WPF) property system. Property value inheritance enables child elements in the element tree to get the value of a specific property from the parent element and inherit the value as if it were set anywhere in the nearest parent element. The parent element can also obtain its value through property value inheritance, so it is possible for the system to recurse all the way to the page root element. Property value inheritance is not the default behavior of the property system; properties must be established with specific metadata settings so that the property can start property value inheritance on child elements.
The original intention of the dependency property inheritance is that the related settings of the parent element will be automatically passed to the child elements of all levels, that is, the element can inherit the value of the dependency property from its parent in the tree. For example, when we modify the font setting of the form parent container control, all levels of child controls will automatically use the font setting (provided that the child control does not make custom settings). Next, let's do 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> <Grid.RowDefinitions> <RowDefinition Height="101*"/> <RowDefinition Height="80"/> <RowDefinition Height="80"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" > <Label Content="Inherit from Window Of FontSize" /> <TextBlock Name="textBlockInherited" Text="Override inheritance, no inheritance Window Of FontSize" FontSize="36" TextWrapping="WrapWithOverflow"/> <StatusBar>Not inherited from Window Of FontSize,Statusbar</StatusBar> </StackPanel> <WrapPanel Grid.Row="1"> <Label Content="Form font size" /> <ComboBox Name="drpWinFontSize"></ComboBox> <Button Name="btnFontSize" Click="btnFontSize_Click">change window Typeface</Button> </WrapPanel> <WrapPanel Grid.Row="2"> <Label Content="Text font size" /> <ComboBox Name="drpTxtFontSize"></ComboBox> <Button Name="btnTextBlock" Click="btnTextBlock_Click">change TextBlock Typeface</Button> </WrapPanel> </Grid> </Window>
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.Navigation; using System.Windows.Shapes; namespace WpfApp4 { /// <summary> ///Interaction logic of MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { 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; } } }
The setting of Window.FontSize will affect the font size of all internal elements, which is called property value inheritance. For example, the first Label in the above code does not define FontSize, so it inherits the value of Window.FontSize. But once the child element provides an explicit setting, the inheritance will be interrupted. For example, the second TextBlock defines its own FontSize, so the inherited value will no longer work at this time.
At this time, you will find a very strange problem: Although StatusBar does not override FontSize, and it is also a child element of Window, its font size does not change, maintaining the system default value. So what's the reason? As a beginner, you may be wondering why the government doesn't say that the principles are like this. Why do they differ from each other? In fact, careful study shows that not all elements support attribute value inheritance. There will be some unexpected situations, which are generally due to the following two aspects:
1. Some Dependency properties specify Inherits as non inheritable when registering with, so inheritance will fail.
2. There are other higher priority settings that set this value. You can see the specific priority level in the previous "priority of dependent properties".
Property values are inherited through the hybrid tree operation. Both the parent holding the original value and the child inheriting the value must be FrameworkElement Or FrameworkContentElement , and all must belong to a logical tree. However, for existing WPF properties that support property inheritance, inheritance of property values can persist through mediation objects that are not in the logical tree. This is mainly applicable to the following situations: let the template element use all the inherited attribute values set on the instance where the template is applied, or use all the inherited attribute values set in the higher level page level component (so it is also higher in the logical tree). In order for inheritance of property values to be consistent in both cases, inherited properties must be registered as additional properties.
The reason is that some controls, such as StatusBar, tooption, and Menu, internally set their font property values to match the current system. This allows users to change their appearance through the operating system's control panel. There is a problem with this method: StatusBar, etc., intercepts attributes inherited from the parent element without affecting its child elements. For example, if we add a Button to the StatusBar. Then the font property of this Button will remain unchanged due to the truncation of StatusBar, and its default value will be retained. So we should pay special attention to these problems when using it.