カスタム *書き込み専用* 依存関係プロパティを作成するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/1315186

質問

書き込み専用の依存関係プロパティを作成する手順を知る必要があります。dependencyProperty クラスには書き込み専用プロパティ用の特別な "Register" メソッドがないことがわかりますが、RegisterAttached メソッドが私がやろうとしていることに適用できるかどうかはわかりません。

このプロパティは、単純な CLR プロパティではなく、依存関係プロパティである必要があります。内部的に、私のクラスは安定した状態を保つために、このプロパティで PropertyChangedCallback を必要とします。

書き込み専用の依存関係プロパティを作成できることは次のとおりです。次のように明確に記載されているためです。
Pro C# 2008 と .NET 3.5 プラットフォーム (1061 ページ).
ただし、同じページで「依存関係プロパティ」と「書き込み専用」を見つけることができるのはここだけです。そしてこの作者は、基本的な読み書き依存関係プロパティ以外の手順を実際に読者に示す必要はないと考えていたようです。もちろんこの本も できた BS の負荷になるかもしれませんが、この本はかなり標準的なように見えるので、著者が正しいことはかなり安全な賭けだと思います。インターネット上に情報が不足しているのは、一般的にこのような物件を作る必要がある人がいないという事実に起因すると思います。

書き込み専用の依存関係プロパティを独自に作成するというのは、非常に疑わしいと思われることは承知しています。私が望んでいるところでは、それが理にかなっていると保証します。私のクラスには、それを設定するオブジェクトにのみ役立つ値を持つプロパティがあります。後で別のオブジェクトがこのプロパティの値を要求した場合、セッターの元のコンテキストが分からなければ、その値から合理的な意味を理解することはできません。

このプロパティは、情報提供を目的としたものではありません。外部オブジェクトがこの方法でプロパティ値を使用しようとすると、問題が発生し、危険であり、セキュリティ リスクになります。したがって、このプロパティに対する読み取り操作を禁止することが最善の設計であると私は考えています。私のクラスを使用する人は誰でも、意図した方法でクラスを使用することを強いられていることに気づくでしょう。その方が、最終的にははるかに良く、よりクリーンに機能するでしょう。

役に立ちましたか?

解決

できません。これは仕様のようです。言及された本に対するあなたのアプローチは理解できますし、その品質に決して疑問を抱いているわけではありませんが、それでもこれはある種のコピー&ペーストまたは同様の問題であると推測します。私の推論は次のとおりです。

WPF プロパティ システム コード

WPF プロパティ システムの設計

  • より重要、 XAML プロセッサの現在の WPF 実装は、本質的に依存関係プロパティを認識します。WPF XAML プロセッサは、バイナリ XAML を読み込んで依存関係プロパティである属性を処理するときに、依存関係プロパティのプロパティ システム メソッドを使用します。これにより、プロパティ ラッパーが効果的にバイパスされます。, 、 見る XAML の読み込みと依存関係のプロパティ.
  • 最も重要な、 '依存関係プロパティは通常、パブリック プロパティであるとみなされる必要があります。Windows Presentation Foundation (WPF) プロパティ システムの性質により、依存関係プロパティ値に関するセキュリティを保証することができません。, 、 見る 依存関係プロパティのセキュリティ.

特に後の 2 つの点は、依存関係プロパティ値に常にアクセスできるという設計上の制約を概説しています。 GetValue()/SetValue(), 、CLR ラッパーがアクセス制限されているか、まったく利用可能であるかに関係なく、唯一の例外は明確に説明されています。 読み取り専用の依存関係プロパティ.

したがって、 ジェフス 答えはすでに暗示していますが、たとえばゲッターを削除するだけでは、誰かが次の方法でプロパティにアクセスするのを実際に防ぐことはできません。 GetValue(), 、ただしこれは少なくとも 'カスタム クラスのすぐに公開される名前空間を減らす'. 。によって提案されているように、プロパティ値の可視性/アクセス性を多少低下させ、取得した値をクライアントにとって本質的に役に立たない、そのようなセマンティックな回避策の有用性。 ジェフ もちろん、特定のシナリオによって異なります。

他のヒント

興味深い、これはまれなシナリオは間違いなく、私はそれが有効に何でより多くのを聞いて興味があると思います。

は、無効な値を(NULLなど)の結合またはGetValueメソッドを通じて読み込みのために提供するというアイデアを考えるのと同じCLRゲッターを持っていないながら、?

ちょうどプライベートメンバ変数

は、あなたが気に「本物」の値を格納するためのプライベートたDependencyPropertyを使用するか、または

は、プロパティで設定された新しい値を離れて格納しながら常に、元の値に値を戻し、コールバックを変更します。

私は今のSilverlightコントロールの開発を行っている私の時間の大半を過ごすので、このプロパティは、WPFとSilverlight-土地で働き、coercianまたはそのような楽しいものを使用していません。多分それはしかし、あなたは正しい軌道に乗って行く取得します。

    /// <summary>
    /// Sets the write-only dependency property.
    /// </summary>
    public string MyWriteOnlyDependencyProperty
    {
        set { SetValue(MyWriteOnlyDependencyPropertyProperty, value); }
    }

    private string _theRealSetValue;

    private bool _ignorePropertyChange;

    /// <summary>
    /// Identifies the MyWriteOnlyDependencyProperty dependency property.
    /// </summary>
    public static readonly DependencyProperty MyWriteOnlyDependencyPropertyProperty =
        DependencyProperty.Register(
            "MyWriteOnlyDependencyProperty",
            typeof(string),
            typeof(TemplatedControl1),
            new PropertyMetadata(null, OnMyWriteOnlyDependencyPropertyPropertyChanged));

    /// <summary>
    /// MyWriteOnlyDependencyPropertyProperty property changed handler.
    /// </summary>
    /// <param name="d">TemplatedControl1 that changed its MyWriteOnlyDependencyProperty.</param>
    /// <param name="e">Event arguments.</param>
    private static void OnMyWriteOnlyDependencyPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TemplatedControl1 source = d as TemplatedControl1;
        if (source._ignorePropertyChange)
        {
            source._ignorePropertyChange = false;
            return;
        }
        string value = e.NewValue as string;

        source._theRealSetValue = value;

        // Revert, since this should never be accessible through a read
        source._ignorePropertyChange = true;
        source.SetValue(e.Property, e.OldValue);
    }
あなたは依存関係プロパティの定義に適用さCoerceValueCallbackを経由してプロパティに関連付けられたFrameworkPropertyMetadataを使用することができますように

に見えます。ただ、第二引数を取るコールバックをインストールし、新しい値は、あなた自身の書き込み専用の機構を介してオブジェクトに渡し、その後、null(または値型、default(T)用)を返します。

これは、「NETが強制する前に元の値を記憶しています」というのは本当だが、それは、データの結合を介して伝播されることはありません。何も漏れない強要値を返しますGetValue呼び出します。

私はバイトのシーケンスである私の主なプロパティの値を一方向コンビニエンスセッターを実装するために、これを使用しています。ユーザは、符号化されたバイト(ASCIIまたはUTF-8、設定されているどのようなプロパティによって)一次プロパティを設定するために、例えば、文字列を結合することができます。しかし、すべてのバイト列は、有効なUTF-8ですので、逆変換をし、便利なプロパティを介して戻って文字列を読み取ることはできません。

public string AsciiData
{
    set { BinaryArray = Encoding.ASCII.GetBytes(value); }
}

public static readonly DependencyProperty AsciiDataProperty =
    DependencyProperty.Register("AsciiData",
        typeof(string),
        typeof(HexView),
        new FrameworkPropertyMetadata(null, CoerceAsciiData));

private static object CoerceAsciiData(DependencyObject target, object value)
{
    (target as HexView).AsciiData = value as string;
    return null;
}

強制ハンドラは、メタデータの交換を介して除去することができますので、これはのセキュリティを提供していないが、それは間違った方法で結合を作成するから、開発者を防ぐことができます。

私はあなただけ持つことができない理由として「get」が便利な何も返さない混乱している?

しかし、さらに、おそらくあなただけのジェフの例では、「OnMyWriteOnlyDependencyPropertyPropertyChanged」を実装していない。

誰が正しい、それを読むことができない場合は、イベントを持っている本当の理由は?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top