1

我正在使用DataTemplateSelector内部 a ContentControlDataTemplates基于 3 个不同,我有 3个不同object types。当我将contentContentControl的数据设置为上述类型的数据时,DataTemplateSelector交换到特定DataTemplate的和选择器似乎会回滚/重置旧模板中的值。为什么呢?

编辑:我发现这些值被重置了,因为我有一个名为 Prop 的附加属性,并且在它的 OnPropertyChangedCallback 内部它通知我在 DataTemplates 之间交换时 Prop 的值为 null。您可以在下面的代码中看到该附加属性。

有人可以帮我弄清楚这种交换机制背后发生了什么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.

选择器如下所示。textDataTemplate它在一个和numericDataTemplate另一个模板之间交换。正如我提到的,我有这三种类型string,我不想提及。他们被称为,还有一个。:)intand one moreDataTemplatestextDataTemplatenumericDataTemplate

<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>

numericDataTemplate看起来类似于textDataTemplate只允许数字。

这是Propattached propertyAttProperties class。位于所有三个 DataTemplate 内部的某个地方type stringProp上面Prop是坐在a上,TextBox但也可能是a Label。这markupextension只是一个“回你好”。该扩展只是为了测试如何创建自定义标记扩展。扩展没什么大不了的。它不应该与交换DataTemplates.

再来一次解释我的问题。交换似乎转售/回滚我的旧模板。我从 textDataTemplate 切换到 numericDataTemplate 并且 textDataTemplate 的 Prop 设置为 null 但之前的值是“Hello”。

为什么会这样?似乎与 using 的行为相同tiggers。一旦 aTrigger不再有效,它就会回滚使用的值。是否DataTemplateSelector使用某种与 相同的机制Triggers

编辑:附加属性只是一个简单的 .RegisterAttached 与 OnPropertyChangedCallback。在 OnPropertyChangedCallback 中,我认为交换 dataTemplates 时道具为空。

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;
        }
    }
}

和 xml:

    <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。ETC..

显然,一切正常,DataTemplateSelector 没有任何问题。我想,您的问题出在您的数据和绑定中

并查看您的 OnClick 方法 - 它始终将 DataContext 设置为 null

于 2013-03-28T19:32:17.107 回答