4

次のように定義されたTextBlockのスタイルにDataTriggerをアタッチしています。

<DataTrigger Binding="{Binding Path=Link, Converter={StaticResource HasContentConverter}}" Value="True">
    <Setter Property="TextDecorations" Value="Underline" />
    <Setter Property="Cursor" Value="Hand" />
</DataTrigger>

私が抱えている問題は、このスタイルを使用することになった複数のオブジェクトがあり、その一部には「Link」プロパティが含まれ、一部には含まれていないことです。システムが検出しないオブジェクトを検出すると、出力ウィンドウに次のエラーが出力されます。

BindingExpressionパスエラー:「リンク」プロパティが「オブジェクト」「DataRowView」(HashCode = 53681904)に見つかりません。BindingExpression:Path = Link; DataItem ='DataRowView'(HashCode = 53681904); ターゲット要素は'TextBlock'(Name ='');です。ターゲットプロパティは「NoTarget」(タイプ「Object」)です

これは予想される動作ですが、XAMLのプロセッサに、「Link」プロパティが存在する場合にのみ適用するように指示する方法があるかどうか疑問に思っています(つまり、バインドを試みる前にプロパティを確認するか、そうでない他のメソッドを使用します)。エラーを出力します)。これは可能ですか?

4

2 に答える 2

1

箱から出して直接それは不可能です。

箱から出してはいけません:次のように動作する独自のBindingExtensionを作成できます:小道具が存在する場合はバインドし、そうでない場合は無視します。また、バインドエラーの報告をオフにすることもできますが、もちろんそれは通常は望ましくありません。

直接ではありません。あるタイプのアタッチされた属性を作成し、バインディングを設定する代わりにそのような属性を設定できます。属性セッターはdatacontext-changesにアタッチし、オブジェクトとビジュアルコンポーネントが飛び回ってバインディングを設定するかどうかを検査します。

直接ではない#2:スタイルとトリガーを「階層化」してみることができます。ご存知のように、トリガーには条件があります。スタイルを2つの部分に分割します。1つは「保護」する必要のない一般的なスタイルで、もう1つは「Blargh」プロパティに依存する機能が含まれています。最初のスタイルをデフォルト/通常として設定します。次に、「DefinesBlargh」または「HasBlarghDefines」と呼ばれる読み取り専用の添付プロパティを作成します。これは、ターゲットオブジェクトのデータコンテキストに実際にそのようなプロパティがあるかどうかを確認します。次に、最初のスタイルに、スタイル付きコントロールの「HasBlarghDefined」が「true」に等しいかどうかを検出するトリガーを追加し、トリガーのアクションで...

...そしてここに問題があります。そこで何をしますか?スタイルをスタイルの2番目の部分に再度置き換えることはできません。これは、おそらくトリガーが削除され、ロジックが非アクティブ化されるためです(ワンショットになります)。または、1回の更新スイープでスタイルを2回変更しようとしたために、単にクラッシュする可能性があります。どうなるかはわかりませんが、「匂い」を感じます。さらに、2番目の部分に変更すると、最初の部分で設定された一般的なものが単純に消去されます。

したがって、実際に実行されてスタイルが置き換えられる場合は、元のトリガーロジックと最初のスタイルの残りが保持されていることを確認する必要があります。つまり、「スタイルの継承」、つまりベースのスタイルを使用することをお勧めします。プロパティ:http ://wpftutorial.net/StyleInheritance.htmlつまり、2つの別々のパーツを作成するのではなく、すべての一般的なもので「ベースパーツ」を作成し、最初のパーツと安全でない余分なものを追加します。現在、特殊な対応物に動的に再置換することは、もう少し合理的です。

または、レイアウトをある程度制御できる場合は、賢くなります。同じコンポーネントに2つのスタイルを適用するのはなぜですか。コントロールの外側の境界に一般的なスタイルを設定し、そこに追加のトリガーを配置し、トリガーに小さな安全でない2番目のスタイルをコントロールに適用させます。

本当にスタイルの両方の部分で1つのコントロールをターゲットにする必要があり、「ベース」を使用できない場合、または単に機能しない場合などは、別の賢いトリックを実行MultiStyleできます。マージするスタイルを定義できるを使用します。 2/3 / +他のスタイルを1つにまとめてから、次のようにトリガー階層を構築します。

multitrigger
   condition: HasBlarghDefined = TRUE
   condition: your own data condition
   setter: set style = multistyle of "generalpart" and "usnafepart"
multitrigger
   condition: HasBlarghDefined = FALSE
   condition: your own data condition
   setter: set style = just a generalpart

私見、それはただうまくいく必要があります。

編集:重要なリンクを通過するのを忘れた:MultiStyle

于 2012-08-13T19:48:10.943 に答える
0

したがって、これに対する私の最終的な解決策は、問題のスタイルを実装する基本DataGridクラスから、「リンク」固有のデータトリガーを除いたものにすることでした。次に、基本クラスから派生した新しいDataGridクラスがあり、データトリガーを具体的に作成するコードが含まれています。

Binding binding = new Binding("Link");
binding.Converter = new MDTCommon.Converters.HasContentConverter();
DataTrigger trigger = new DataTrigger();
trigger.Binding = binding;
trigger.Value = true;
Setter setter1 = new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline);
Setter setter2 = new Setter(TextBlock.CursorProperty, Cursors.Hand);
trigger.Setters.Add(setter1);
trigger.Setters.Add(setter2);
Style style = FindResource("DefaultStyleInQuestion") as Style;
style.Triggers.Add(trigger);

「Link」プロパティを持つバインディングオブジェクトは、派生したDataGridクラスでのみ使用されていたため、このメソッドを使用できました。

于 2012-08-15T15:37:55.047 に答える