web-dev-qa-db-ja.com

添付プロパティはWPFでどの程度正確に機能しますか?

添付プロパティが実際に親要素または子要素のいずれかに値を伝達する方法について、少し不思議に思っています。 TextElement.FontFamilyは、子要素にそのプロパティに割り当てられた値を継承させます(一見ダウンストリーム操作、親から子)。 Grid.Columnは、親アイテムにその子を特定の位置に表示させます(一見上流の操作、子から親)。添付プロパティ値は、どのようにして上向きまたは下向きに流れるかを認識しますか?これについての私の概念は間違っていますか、それともこれらすべてを見通しに入れる部分が欠けていますか?

<StackPanel TextElement.FontFamily="Wingdings">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Button Grid.Column="1" Content="My Button"/>
    </Grid>
</StackPanel>
23
Mark Carpenter

ここには2つの概念があります:依存関係プロパティ添付依存関係プロパティ。 「添付プロパティ」は依存関係プロパティであるため、依存関係をサポートします プロパティ値の継承

基本的な依存関係プロパティについては、非常に大まかな説明として、基本的にwpf(論理/ビジュアル)ツリーの親要素から値を継承します。 メタデータFrameworkPropertyMetadataOptionsInheritフラグ、そして多くの場合これはそうです。

添付プロパティは、 DependencyObject.SetValue メソッドを介して任意のwpfオブジェクト(基本的には少なくともDependencyObject)に設定できるプロパティです。このメカニズムの目的は、子オブジェクト自体ではなく、親オブジェクトに必要な情報を他のオブジェクトに「アタッチ」することです。たとえば、 Grid.Row は、グリッドがレンダリング領域内にアイテムを配置するために必要な添付プロパティです。

依存関係のプロパティは、wpfオブジェクトシステムによって自動的に「下向き」に継承されます。

アタッチされたプロパティは、特定のオブジェクトのコードで明示的に「上向き」に検査されます。グリッドの場合、アイテムを配置する場所を決定すると、含まれている各アイテムのGrid.RowおよびGrid.Columnにアタッチされたプロパティの値をチェックします。

また、アタッチされているオブジェクトを何らかの方法で変更するカスタムアタッチプロパティを作成する手法もよくあります(たとえば、 アタッチされたプロパティを介したドラッグアンドドロップ機能 )。

追記として、アタッチされたプロパティを継承する良い例は TextElement.FontFamily です。 Grid.RowプロパティとGrid.Columnプロパティには、継承フラグが設定されていません。

TextElement.FontFamily、Reflectorから:

 FontFamilyProperty = DependencyProperty.RegisterAttached("FontFamily", typeof(FontFamily), typeof(TextElement), new FrameworkPropertyMetadata(SystemFonts.MessageFontFamily, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(TextElement.IsValidFontFamily));

Grid.Row、Reflectorから:

 RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged)), new ValidateValueCallback(Grid.IsIntValueNotNegative));
43
Kenan E. K.

から [〜#〜] msdn [〜#〜]

アタッチされたプロパティはどのオブジェクトにも設定可能ですが、プロパティを設定すると具体的な結果が得られることや、値が別のオブジェクトによって使用されることを自動的に意味するわけではありません。一般に、アタッチされたプロパティは、さまざまな可能なクラス階層または論理関係からのオブジェクトが、アタッチされたプロパティを定義するタイプに共通の情報をそれぞれ報告できるようにすることを目的としています。アタッチされたプロパティを定義するタイプは、通常、次のいずれかのモデルに従います。

  • アタッチされたプロパティを定義するタイプは、アタッチされたプロパティの値を設定する要素の親要素になるように設計されています。次に、型は、オブジェクトツリー構造に対して内部ロジックを介して子オブジェクトを反復し、値を取得して、何らかの方法でそれらの値に作用します。

  • アタッチされたプロパティを定義するタイプは、さまざまな可能な親要素およびコンテンツモデルの子要素として使用されます。

  • 添付プロパティを定義するタイプは、サービスを表します。他のタイプは、添付プロパティの値を設定します。次に、プロパティを設定する要素がサービスのコンテキストで評価されると、添付されたプロパティ値がサービスクラスの内部ロジックを介して取得されます。

親定義の添付プロパティの例

WPFが添付プロパティを定義する最も一般的なシナリオは、親要素が子要素コレクションをサポートし、動作の詳細が子要素ごとに個別に報告される動作を実装する場合です。

DockPanelはDockPanel.Dockアタッチプロパティを定義し、DockPanelにはレンダリングロジックの一部としてクラスレベルのコードがあります(具体的には、MeasureOverrideとArrangeOverride)。 DockPanelインスタンスは、その直接の子要素のいずれかがDockPanel.Dockの値を設定しているかどうかを常に確認します。その場合、それらの値は、その特定の子要素に適用されるレンダリングロジックの入力になります。ネストされたDockPanelインスタンスはそれぞれ、独自の直接の子要素コレクションを処理しますが、その動作は、DockPanelがDockPanel.Dock値を処理する方法に固有の実装です。理論的には、直接の親以外の要素に影響を与えるプロパティを添付することは可能です。 DockPanel.Dock添付プロパティが、それに作用するDockPanel親要素を持たない要素に設定されている場合、エラーや例外は発生しません。これは単に、グローバルプロパティ値が設定されているが、情報を消費できる現在のDockPanel親がないことを意味します。

3
Charlie

簡単に言えば、これは私がそれを理解する方法です(私が間違っている場合は私を訂正してください)。

オブジェクト(A)は、別のオブジェクト(B)にアタッチするプロパティを実装します(オブジェクトBは、この「アタッチ可能な」プロパティの存在についてさえ知りません)。オブジェクトBはDependencyObjectから継承する必要があります。

オブジェクトAは、他のオブジェクトA.GetAttachedProperty(B)の「アタッチ可能」プロパティをチェックする静的メソッドも実装します。

BがAからアタッチされたプロパティを持っている場合、A.GetAttachedPropertyはその値を読み取って返します。それ以外の場合、Aはそれを読み取ろうとし、そこにないためnullを返します。

0
Carlo