1

DataTemplateSelectorの中でを使用していContentControlます。私は3つの異なるDataTemplatesに基づいて3つの異なるを持っていobject typesます。上記のタイプのデータにcontentmyを設定すると、特定のデータへのスワップが行われ、さらにセレクターが古いテンプレートから値をロールバック/リセットするように見えます。どうしてこんなことに?ContentControlDataTemplateSelectorDataTemplate

編集: Prop という名前の添付プロパティがあり、その OnPropertyChangedCallback 内で、DataTemplate 間のスワップ時に値が null である Prop について通知されるため、値がリセットされることがわかりました。以下のコードでその添付プロパティを確認できます。

のこのスワッピングメカニズムの背後で何が起こっているのか、誰か助けてもらえますかDataTemplateSelector?

コードを使用した詳細な説明は次のとおりです。

public void Window1()
{
  InitalizeComponents();
}

public void OnClick(object sender, RoutedEventArgs e)
{
  if(this.DataContext == null)
    this.DataContext = "Hallo";
 else{
  if(this.DataContext is string)
    this.DataContext = 123;
  else{
   if(this.DataContext is int)
     this.DataContext = null;
   }
  }
}
By clicking on Button few times I change the type and so in ContentControl the selector changes to DataTemplate.

セレクターは以下のようになります。とtextDataTemplatenumericDataTemplateもう 1 つのテンプレートを切り替えます。私が述べたように、私は言及したくない 、 、stringint3つのタイプを持っています。and one moreそれらDataTemplatesは と呼ばれtextDataTemplatenumericDataTemplateもう 1 つです。:)

<local:MyTemplateSelector x:Key="dataTemplateSelector"
                                 TextTemplate="{StaticResource textDataTemplate}"
                                 NumericTemplate="{StaticResource numericDataTemplate}"/>

public class MyTemplateSelector : DataTemplateSelector
{
  public DataTemplate TextTemplate;

  public DataTemplate NumericTemplate;


  public DataTemplate Select(object item, Culture.....)
  {
    if(item is string)
    {
      return this.TextTemplate;
    }
    else
    {
      return this.NumericTemplate;
    }
  }
}

ContentControlXAML は次のようになります。

<Button Click="OnClick" Content="Click Me"/>


<ContentControl Name="contentCtrl"
                Content="{Binding}"
                Width="123"
                ContentTemplateSelector="{StaticResource dataTemplateSelector}" />

そして、これがtextDataTemplate似ている方法です。

<DataTemplate x:Key="textDataTemplate">
    <TextBox  x:Name="text" my:AttProperties.Prop="{extension:MarkupExt value}" Text="{Binding Path=Txt, Mode=Default, UpdateSourceTrigger=Explicit}"/>
</DataTemplate>

numericDataTemplatetextDataTemplate数字のみが許可されているという点だけに似ています。

Prop私のattached propertyからAttProperties classの ですtype string。はProp、3 つの DataTemplate すべての内部にあります。上は上にProp座っていますTextBoxが、それも上にある可能性がありLabelます。はmarkupextension単なる「return Hello」です。拡張機能は、カスタム マークアップ拡張機能の作成方法をテストするためのものです。拡張子に大した問題はありません。のスワッピングとはあまり関係がないはずですDataTemplates

私の問題を説明するためにもう一度。スワップすると、古いテンプレートが再設定/ロールバックされるようです。私は textDataTemplate から numericDataTemplate と言うことができ、textDataTemplate の Prop は null に設定されますが、以前の値は "Hello" でした。

なぜそれが起こっているのですか?を使用した場合と同じ動作のようtiggersです。aTriggerが無効になると、使用された値がロールバックされます。はDataTemplateSelectorと同じメカニズムを使用していTriggersますか?

編集済み:添付プロパティは、OnPropertyChangedCallback を使用した単純な .RegisterAttached です。OnPropertyChangedCallback 内では、dataTemplates を交換するときにプロップが null であることがわかりました。

4

1 に答える 1

3

数値テンプレートで双方向バインディングを使用し、Double などのみを受け入れる場合、値を数値に設定できます。しかし、完全なコードを見ない限り、誰も確信を持てません。独自のコードが何か間違っている可能性があります。理解を深めるために、ContentControl から派生した独自のコントロールを作成し、サンプルで使用します。次に、コントロール メソッド OnContentxxxChanged をオーバーライドし、そこにブレークポイントを挿入して、アプリケーションをデバッグします。データとテンプレート セレクターで何が起こっているかを理解する必要があります。アプリケーションがブレークポイントで停止したら、すべての値を注意深く確認し、スタック トレースを調べます。バインディングをデバッグするには、IValueConverters を挿入できます。これにより、コード内で値を確認できる場所が得られます。

最初に最も単純な機能を作成してから、質問に表示されなかったコントロールのプロパティへの双方向バインディングを持つテキストボックスなどのより複雑なものに進むことをお勧めします。TextBlocks を使用した作業バージョンを次に示します。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    public void OnClick(object sender, RoutedEventArgs e)
    {
        if (this.DataContext == null)
            this.DataContext = "Hallo";

        else if (this.DataContext is string)
            this.DataContext = 123;

        else if (this.DataContext is int)
            this.DataContext = null;
    }
}
public class MyTemplateSelector : DataTemplateSelector
{
    public DataTemplate TextTemplate {get; set;}

    public DataTemplate NumericTemplate {get; set;}

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is string)
        {
            return this.TextTemplate;
        }
        else
        {
            return this.NumericTemplate;
        }
    }
}

およびxaml:

    <Grid>
    <Grid.Resources>
        <DataTemplate x:Key="numericDataTemplate">
            <TextBlock Foreground="Red" Text="{Binding}" />
        </DataTemplate>
        <DataTemplate x:Key="textDataTemplate">
            <TextBlock Foreground="Green" Text="{Binding}"/>
        </DataTemplate>
        <local:MyTemplateSelector x:Key="dataTemplateSelector"
                             TextTemplate="{StaticResource textDataTemplate}"
                             NumericTemplate="{StaticResource numericDataTemplate}"/>
    </Grid.Resources>
    <StackPanel>
        <Button Click="OnClick" Content="Click Me" VerticalAlignment="Top"/>
        <ContentControl Name="contentCtrl"
                Content="{Binding}" 
                Width="300" Height="100" 
                ContentTemplateSelector="{StaticResource dataTemplateSelector}" />
        </StackPanel>
</Grid>

コードと比較してください。DataTemplateSelector から継承する場合は、SelectTemplate メソッドをオーバーライドする必要があり、他の名前のメソッドを作成しないでください。ContentControl などのすべてのコントロールは、SelectTemplate のみを使用します。等..

明らかに、すべてが機能し、DataTemplateSelector は何の問題もありません。あなたの問題はデータとバインディングのどこかにあると思います

そして、あなたの OnClick メソッドを見てください - それは常に DataContext を null に設定します

于 2013-03-28T19:32:17.107 に答える