Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF:依赖项属性与常规CLR属性的区别是什么?_Wpf_Dependency Properties - Fatal编程技术网

WPF:依赖项属性与常规CLR属性的区别是什么?

WPF:依赖项属性与常规CLR属性的区别是什么?,wpf,dependency-properties,Wpf,Dependency Properties,在WPF中,“依赖属性”到底意味着什么 我读过微软的,但它并没有真正让我着迷。那篇文章的部分内容是: 样式和模板是使用依赖属性的两个主要激励场景。样式对于设置定义应用程序用户界面(UI)的属性特别有用。样式通常在XAML中定义为资源。样式与属性系统交互,因为它们通常包含特定属性的“setter”,以及基于另一个属性的实时值更改属性值的“触发器” 然后示例代码如下所示: <Style x:Key="GreenButtonStyle"> <Setter Property="Co

在WPF中,“依赖属性”到底意味着什么

我读过微软的,但它并没有真正让我着迷。那篇文章的部分内容是:

样式和模板是使用依赖属性的两个主要激励场景。样式对于设置定义应用程序用户界面(UI)的属性特别有用。样式通常在XAML中定义为资源。样式与属性系统交互,因为它们通常包含特定属性的“setter”,以及基于另一个属性的实时值更改属性值的“触发器”

然后示例代码如下所示:

<Style x:Key="GreenButtonStyle">
  <Setter Property="Control.Background" Value="Green"/>
</Style>
....
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>

....
我是绿色的!
但我不明白这有什么特别之处。这是否意味着,当我将按钮上的
Style
设置为给定样式时,实际上是在隐式设置
Background
?这是问题的关键吗

在WPF中,“依赖属性”到底意味着什么

为了成为依赖属性,该属性实际上必须静态地定义为类上的。依赖项属性系统与标准CLR属性非常不同

但是,依赖项属性的处理方式非常不同。类型以静态方式定义依赖项属性,并提供默认值。在需要实例之前,运行时实际上不会为实例生成值。这提供了一个好处——属性只有在请求类型时才存在,因此您可以拥有大量属性而不会产生开销

这就是使样式化属性起作用的原因,但对于允许附加属性、通过可视树的属性“继承”以及WPF依赖的许多其他内容也很重要


例如,以
DataContext
依赖项属性为例。通常,为窗口或用户控件设置
DataContext
依赖项属性。默认情况下,该窗口中的所有控件自动“继承”其父控件的
DataContext
proeprty,这允许您为控件指定数据绑定。使用标准CLR属性,您需要为窗口中的每个控件定义DataContext,以使绑定正常工作。

以下是我一直希望有人为我编写的关于依赖项属性如何工作的解释。这是不完整的,而且很可能是错误的,但它将帮助您对它们有足够的理解,从而能够掌握您所阅读的文档

依赖属性是通过
DependencyObject
类的方法获取和设置的类似属性的值。它们可以(而且通常确实)看起来非常像CLR属性,但它们不是。这是关于他们的第一件令人困惑的事情。依赖属性实际上是由几个组件组成的

下面是一个例子:

Document
RichTextBox
对象的属性。这是一个真正的CLR属性。也就是说,它有一个名称、一个类型、一个getter和一个setter,就像任何其他CLR属性一样。但是与“普通”属性不同,
RichTextBox
属性不仅仅在实例中获取和设置私有值。在内部,它是这样实现的:

public FlowDocument Document
{
   get { return (FlowDocument)GetValue(DocumentProperty); }
   set { SetValue(DocumentProperty, value); }
}
public static DependencyProperty DocumentProperty = DependencyProperty.Register(
    "Document",
    typeof(FlowDocument), 
    typeof(RichTextBox));
设置
Document
时,传入的值将与
DocumentProperty
一起传递到
SetValue
。那是什么?那么
GetValue
是如何得到它的值的呢?还有…为什么

首先是什么。
RichTextBox
上定义了一个名为
DocumentProperty
的静态属性。声明此属性时,其操作如下:

public FlowDocument Document
{
   get { return (FlowDocument)GetValue(DocumentProperty); }
   set { SetValue(DocumentProperty, value); }
}
public static DependencyProperty DocumentProperty = DependencyProperty.Register(
    "Document",
    typeof(FlowDocument), 
    typeof(RichTextBox));
在本例中,
Register
方法告诉依赖属性系统,
RichTextBox
——类型,而不是实例——现在有一个名为
Document
的类型为
FlowDocument
的依赖属性。此方法将此信息存储在某处。其中,确切地说,是一个对我们隐藏的实现细节

文档
属性的setter调用
设置值
时,
设置值
方法查看
文档属性
参数,验证它确实是属于
RichTextBox
的属性,并且
是正确的类型,然后将其新值存储在某处。
DependencyObject
的文档对这个实现细节并不熟悉,因为您实际上不需要了解它。在我关于这些东西如何工作的心智模型中,我假设有一个
Dictionary
类型的属性是
DependencyObject
的私有属性,因此派生类(如
RichTextBox
)看不到它,但
GetValue
SetValue
可以更新它。但谁知道呢,也许是修道士写在羊皮纸上的

无论如何,这个值现在被称为“本地值”,也就是说它是这个特定
RichTextBox
的本地值,就像普通属性一样

所有这些的要点是:

  • CLR代码不需要知道属性是依赖属性。它看起来和其他任何财产都一模一样。您可以调用
    GetValue
    SetValue
    来获取和设置它,但是除非您正在对依赖属性系统进行操作,否则您可能不需要这样做
  • 与普通属性不同,获取和设置属性时可能会涉及到它所属对象以外的其他对象。(可以想象,你可以通过反射来实现这一点,但反射很慢。在字典中查找东西很快。)
  • 这个东西(即依赖属性系统)本质上位于对象及其依赖属性之间。它可以做各种各样的事情
  • 什么东西?好吧,让我们看一看
        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 SampleWPF
        {
            /// <summary>
            /// Interaction logic for MainWindow.xaml
            /// </summary>
            public partial class MainWindow : Window
            {
                public static readonly DependencyProperty Count1Property;
                private int _Count2 = 2;
                public int Count2
                {
                    get { return _Count2; }
                    set { _Count2 = value; }
                }
                public MainWindow()
                {
                    return;
                }
                static MainWindow()
                {
                    // Register the property
                    MainWindow.Count1Property = 
                        DependencyProperty.Register("Count1",
                        typeof(int), typeof(MainWindow),
                        new FrameworkPropertyMetadata(1,
                        new PropertyChangedCallback(OnCount1Changed)));
                }
                // A .NET property wrapper (optional)
                public int Count1
                {
                    get { return (int)GetValue(MainWindow.Count1Property); }
                    set { SetValue(MainWindow.Count1Property, value); }
                }
                // A property changed callback (optional)
                private static void OnCount1Changed(
                  DependencyObject o, DependencyPropertyChangedEventArgs e) {
    
                }
                private void btnButton1_Click_1(object sender, RoutedEventArgs e)
                {
                    Count1++;
                }
                private void btnButton1_Click_2(object sender, RoutedEventArgs e)
                {
                    Count2++;
                }
            }
        }
    
    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
      FontSize="30" FontStyle="Italic"
      Background="OrangeRed">
      <StackPanel>
        <Label FontWeight="Bold" FontSize="20" Foreground="White">
          WPF Unleashed (Version 3.0)
        </Label>
        <Label>© 2006 SAMS Publishing</Label>
        <Label>Installed Chapters:</Label>
        <ListBox>
          <ListBoxItem>Chapter 1</ListBoxItem>
          <ListBoxItem>Chapter 2</ListBoxItem>
        </ListBox>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
          <Button MinWidth="75" Margin="10">Help</Button>
          <Button MinWidth="75" Margin="10">OK</Button>
        </StackPanel>
        <StatusBar>You have successfully registered this product.</StatusBar>
      </StackPanel>
    </Window>