唯讀相依性屬性Read-Only Dependency Properties

本主題說明唯讀相依性屬性,包括現有的唯讀相依性屬性,以及用於建立自訂唯讀相依性屬性的案例和技術。This topic describes read-only dependency properties, including existing read-only dependency properties and the scenarios and techniques for creating a custom read-only dependency property.

PrerequisitesPrerequisites

本主題假設您已了解實作相依性屬性的基本案例,以及如何將中繼資料套用到自訂相依性屬性。This topic assumes that you understand the basic scenarios of implementing a dependency property, and how metadata is applied to a custom dependency property. 如需相關內容,請參閱自訂相依性屬性相依性屬性中繼資料See Custom Dependency Properties and Dependency Property Metadata for context.

現有的唯讀相依性屬性Existing Read-Only Dependency Properties

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 架構中定義的一些相依性屬性為唯讀狀態。Some of the dependency properties defined in the Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) framework are read-only. 指定唯讀相依性屬性的一般原因是,這些屬性應該用來判斷狀態,然而該狀態會受到許多因素影響,但從使用者介面設計觀點來看,只將屬性設為該狀態並不恰當。The typical reason for specifying a read-only dependency property is that these are properties that should be used for state determination, but where that state is influenced by a multitude of factors, but just setting the property to that state isn't desirable from a user interface design perspective. 例如,屬性 IsMouseOver 實際上只會呈現從滑鼠輸入決定的狀態。For example, the property IsMouseOver is really just surfacing state as determined from the mouse input. 藉由規避實際的滑鼠輸入,以程式設計方式設定此值的任何嘗試,都是無法預測且會導致不一致的情況。Any attempt to set this value programmatically by circumventing the true mouse input would be unpredictable and would cause inconsistency.

由於是不可設定的,因此,唯讀相依性屬性不適合許多相依性屬性通常可提供解決方案 (也就是:資料繫結、可直接設定的樣式值、驗證、動畫、繼承) 的案例。By virtue of not being settable, read-only dependency properties aren't appropriate for many of the scenarios for which dependency properties normally offer a solution (namely: data binding, directly stylable to a value, validation, animation, inheritance). 儘管不可設定,唯讀相依性屬性仍然具有一些屬性系統中相依性屬性所支援的其他功能。Despite not being settable, read-only dependency properties still have some of the additional capabilities supported by dependency properties in the property system. 其餘最重要的功能是,唯讀相依性屬性仍可用來做為樣式中的屬性觸發程序。The most important remaining capability is that the read-only dependency property can still be used as a property trigger in a style. 您無法使用一般 common language runtime (CLR)屬性來啟用觸發程式。它必須是相依性屬性。You can't enable triggers with a normal common language runtime (CLR) property; it needs to be a dependency property. 前述的 IsMouseOver 屬性是一個案例的最佳範例,其中可能非常適合用來定義控制項的樣式,其中某些可見屬性(例如背景、前景或控制項中複合元素的類似屬性)將會當使用者將滑鼠放在控制項的某個定義區域時進行變更。The aforementioned IsMouseOver property is a perfect example of a scenario where it might be quite useful to define a style for a control, where some visible property such as a background, foreground, or similar properties of composited elements within the control will change when the user places a mouse over some defined region of your control. 屬性系統固有的失效處理序也可以偵測到並回報唯讀相依性屬性中的變更,這實際上可在內部支援屬性觸發程序功能。Changes in a read-only dependency property can also be detected and reported by the property system's inherent invalidation processes, and this in fact supports the property trigger functionality internally.

建立自訂唯讀相依性屬性Creating Custom Read-Only Dependency Properties

請務必閱讀前一節,以了解為什麼唯讀相依性屬性不適用許多一般的相依性屬性案例。Make sure to read the section above regarding why read-only dependency properties won't work for many typical dependency-property scenarios. 但是,如果您有適當的案例,您可能想要建立自己的唯讀相依性屬性。But if you have an appropriate scenario, you may wish to create your own read-only dependency property.

在建立唯讀相依性屬性的處理序中,許多部分與自訂相依性屬性實作相依性屬性主題中所述的相同。Much of the process of creating a read-only dependency property is the same as is described in the Custom Dependency Properties and Implement a Dependency Property topics. 有三個重大差異:There are three important differences:

  • 註冊屬性時,請呼叫 RegisterReadOnly 方法,而不是屬性註冊的一般 Register 方法。When registering your property, call the RegisterReadOnly method instead of the normal Register method for property registration.

  • 在執行 CLR 「包裝函式」屬性時,請確定包裝函式也沒有設定的執行,如此您公開的公用包裝函式就不會有不一致的唯讀狀態。When implementing the CLR "wrapper" property, make sure that the wrapper too doesn't have a set implementation, so that there is no inconsistency in read-only state for the public wrapper you expose.

  • 唯讀註冊所傳回的物件是 DependencyPropertyKey,而不是 DependencyPropertyThe object returned by the read-only registration is DependencyPropertyKey rather than DependencyProperty. 您仍應將此欄位儲存為成員,但通常不需讓它成為類型的公用成員。You should still store this field as a member but typically you would not make it a public member of the type.

不論您必須支援的私用欄位或值為何,當然都能使用您決定的任何邏輯完整寫入您的唯讀相依性屬性。Whatever private field or value you have backing your read-only dependency property can of course be fully writable using whatever logic you decide. 不過,一開始或做為執行時間邏輯的一部分設定屬性最直接的方式,就是使用屬性系統的 Api,而不是避開屬性系統並直接設定私用支援欄位。However, the most straightforward way to set the property either initially or as part of runtime logic is to use the property system's APIs, rather than circumventing the property system and setting the private backing field directly. 特別是,SetValue 的簽章會接受 DependencyPropertyKey類型的參數。In particular, there is a signature of SetValue that accepts a parameter of type DependencyPropertyKey. 您在應用程式邏輯中設定此值的方式和位置,將會影響您在第一次註冊相依性屬性時所建立的 DependencyPropertyKey 上,您可能想要設定存取權的方式。How and where you set this value programmatically within your application logic will affect how you may wish to set access on the DependencyPropertyKey created when you first registered the dependency property. 如果您全都在類別內處理此邏輯,您可能會讓它成為私用,或者如果您需要從組件的其他部分設定它,則可能會將它設為內部。If you handle this logic all within the class you could make it private, or if you require it to be set from other portions of the assembly you might set it internal. 其中一個方法是在相關事件的類別事件處理常式中呼叫 SetValue,通知類別實例必須變更儲存的屬性值。One approach is to call SetValue within a class event handler of a relevant event that informs a class instance that the stored property value needs to be changed. 另一個方法是使用配對的 PropertyChangedCallback 將相依性屬性結合在一起,並在註冊期間 CoerceValueCallback 回呼做為這些屬性中繼資料的一部分。Another approach is to tie dependency properties together by using paired PropertyChangedCallback and CoerceValueCallback callbacks as part of those properties' metadata during registration.

因為 DependencyPropertyKey 是私用的,而且不是由您程式碼外部的屬性系統所傳播,所以唯讀相依性屬性會比讀寫相依性屬性更能設定安全性。Because the DependencyPropertyKey is private, and is not propagated by the property system outside of your code, a read-only dependency property does have better setting security than a read-write dependency property. 針對讀寫相依性屬性,識別欄位是明確或隱含公開的,因此該屬性是可廣泛設定的。For a read-write dependency property, the identifying field is explicitly or implicitly public and thus the property is widely settable. 如需詳細資訊,請參閱相依性屬性的安全性For more specifics, see Dependency Property Security.

請參閱See also