2

いくつかのカスタム状態のプロパティに応じて、関連するXAMLファイルのリソースとしてすべて定義されているさまざまなContentTemplatesをスワップするUserControl(見た目のないカスタムコントロールではありません)があります。コードビハインドでは、スワップインされたContentTemplatesの要素の1つを見つける必要があります。

ルックレスコントロール(つまり、カスタムコントロール)では、OnApplyTemplateをオーバーライドしてから、FindNameを使用しますが、ContentTemplateがトリガーによって切り替えられたときにそのオーバーライドは発生しません(少なくともUserControlの場合はそうではありません。私はしていません)。カスタムコントロールを使用してその機能をテストしました。)

ここで、Loadedイベントをスワップインされたテンプレートのコントロールに接続してみました。これはコードビハインドで発生します。次に、「sender」をクラスレベルの変数に格納します。ただし、Unloadedイベントをサブスクライブしてその値をクリアしようとすると、tempalteがスワップアウトされて、呼び出される前にそのイベントの配線が解除され、コントロールが画面からサイレントにアンロードされるため、このイベントは発生しません。しかし、私はまだコードビハインドでそのハングした参照を持っています。

OnApplyTemplate機能をシミュレートするために、ContentTemplateChanged通知をサブスクライブし、VisualTreeHelperを使用して必要なコントロールを探すことを検討していますが、もっと良い方法があるかどうか疑問に思っているので、この投稿をご覧ください。

何か案は?

参考までに、これは私が持っているコントロールの非常に簡略化された例です。この例では、IsEditingがtrueの場合、「FindMe」という名前のテキストボックスを検索します。IsEditingがfalseの場合、つまりContentTemplateがスワップインされていない場合、「null」を取得したい...

<UserControl x:Class="Crestron.Tools.ProgramDesigner.Controls.EditableTextBlock"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Crestron.Tools.ProgramDesigner.Controls"
    x:Name="Root">

    <UserControl.Resources>

        <DataTemplate x:Key="EditModeTemplate">

            <TextBox x:Name="FindMe"
                Text="{Binding Text, ElementName=Root}" />

        </DataTemplate>

        <Style TargetType="{x:Type local:EditableTextBlock}">
            <Style.Triggers>

                <Trigger Property="IsEditing" Value="True">
                    <Setter Property="ContentTemplate" Value="{StaticResource EditModeTemplate}" />
                </Trigger>

            </Style.Triggers>
        </Style>

    </UserControl.Resources>

    <TextBlock x:Name="TextBlock"
        Text="{Binding Text, ElementName=Root}" />

</UserControl>

Aaaaaaand GO!

M

4

1 に答える 1

2

残念ながら、これ以上の方法はありません。イベントに接続する代わりに、 OnContentTemplateChangedをオーバーライドできます。

実際の要素を取得するには、 DataTemplate.FindNameメソッドを使用する必要があります。リンクには、そのメソッドの使用方法の例があります。

ただし、OnContentTemplateChangedを使用している場合は、基になるContentPresenterにすぐには適用されないため、FindNameの呼び出しを遅らせる必要があります。何かのようなもの:

protected override void OnContentTemplateChanged(DataTemplate oldContentTemplate, DataTemplate newContentTemplate) {
    base.OnContentTemplateChanged(oldContentTemplate, newContentTemplate);

    this.Dispatcher.BeginInvoke((Action)(() => {
        var cp = FindVisualChild<ContentPresenter>(this);
        var textBox = this.ContentTemplate.FindName("EditTextBox", cp) as TextBox;
        textBox.Text = "Found in OnContentTemplateChanged";
    }), DispatcherPriority.DataBind);
}

または、UserControlのLayoutUpdatedイベントにハンドラーをアタッチできる場合もありますが、これは必要以上に頻繁に発生する可能性があります。ただし、これは暗黙的なDataTemplatesの場合も処理します。

このようなもの:

public UserControl1() {
    InitializeComponent();
    this.LayoutUpdated += new EventHandler(UserControl1_LayoutUpdated);
}

void UserControl1_LayoutUpdated(object sender, EventArgs e) {
    var cp = FindVisualChild<ContentPresenter>(this);
    var textBox = this.ContentTemplate.FindName("EditTextBox", cp) as TextBox;
    textBox.Text = "Found in UserControl1_LayoutUpdated";
}
于 2011-04-15T11:33:38.047 に答える