TL-DR バージョン:
トリガーが有効な場合の DataTemplate の自動適用と、トリガーが有効でない場合の DataTemplate.LoadContent() の手動呼び出しの違いを理解しようとしています。
詳細は今...
しかし、最初に、この質問は、フレームワークとその内部での動作を理解するのに役立つことから始めましょう。そのため、関連するコードは質問自体を厳密に示すためのものであり、実際のコードを表すものではありません。彼らが言うように、これは説明のみを目的としています。(避けられない「あなたがやろうとしていることを理解していません」または「それは私がやろうとしている方法ではない」という反応を避けようとしているだけです。繰り返しますが、それは質問をサポートするためのものです。それが理にかなっていることを願っています。)
とはいえ、この XAML が String の DataTemplate を 2 つのトリガー (それぞれが異なる要素を対象とする) で定義していると考えてください...
xmlns:system="clr-namespace:System;assembly=mscorlib"
...
<DataTemplate DataType="{x:Type system:String}">
<Border x:Name="Bd" Background="Yellow">
<TextBlock x:Name="Tb" Text="{Binding StringFormat='Formatted Value: {0}'}" />
</Border>
<DataTemplate.Triggers>
<Trigger SourceName="Bd" Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="Red" />
</Trigger>
<Trigger SourceName="Tb" Property="IsMouseOver" Value="True">
<Setter TargetName="Tb" Property="Foreground" Value="Yellow" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
次に、そのテンプレートがスコープ内にある XAML の別の場所に、これがあります...
<ContentPresenter x:Name="TestPresenter" Content="This is a Test" />
...期待どおりに動作します。コードでは、次のように、展開されたテンプレート (Border) のルート要素にアクセスできます...
var expandedTemplateRootElement = VisualTreeHelper.GetChild(TestPresenter, 0) as FrameworkElement;
...しかし、トリガーはどのように、どこに適用されるのでしょうか? それらは明らかに機能しますが、expandedTemplateRootElement.Triggers.Count と TestPresenter.Triggers.Count の両方がゼロを返します。
質問のタイトル自体に記載されているように、このように DataTemplate からコンテンツを手動で展開しようとすると...
var rawContents = "Show me the money!";
var dataTemplateToUse = TestPresenter.FindResource(new DataTemplateKey(rawContents.GetType()));
var expandedTemplateRootElement = dataTemplateToUse.LoadContent() as FrameworkElement;
expandedTemplateRootElement.DataContext = rawContents;
SomeOtherPresenter.Contents = expandedTemplateRootElement;
...これは 2 番目の ContentPresenter (ここでは SomeOtherPresenter と呼ばれます) の Border と TextBlock を正しく表示しますが、dataTemplateToUse.Triggersは2 つが定義されていることを示していますが、機能しません!
私は見つけようとしています
- a) そうしない理由、および
- b) どのように有効化/適用できますか。
もちろん、「チート」は、単に新しい ContentPresenter を起動し、そのコンテンツを設定してから、その ContentTemplate を問題の DataTemplate に設定することです。次に、全体を別の ContentPresenter に詰め込んで、フレームワークに詳細を心配させることができます.
var rawContents = "Hello World";
var dataTemplateToUse = TestPresenter.FindResource(new DataTemplateKey(rawContents.GetType())) as DataTemplate;
var innerPresenter = new ContentPresenter()
{
Content = rawContents,
ContentTemplate = dataTemplateToUse
};
YetAnotherPresenter.Content = innerPresenter;
...しかし、自動展開と手動展開の場合に、展開されたコンテンツ自体にトリガーが実際にどのように適用されるかはまだ説明されていません。
この投稿全体は、まったく異なる方法を尋ねました... DataTemplate で定義されたものを模倣して、FrameworkElements にトリガーをプログラムで作成することは可能ですか (名前が一致し、名前のスコープなどを考慮している場合)。