首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DataTemplateSelector及其怪异行为

DataTemplateSelector及其怪异行为
EN

Stack Overflow用户
提问于 2013-03-21 10:02:03
回答 1查看 2.3K关注 0票数 1

我在ContentControl中使用一个ContentControl。我有3种不同的DataTemplates,基于3种不同的object types。当我将ContentControlContentControl设置为上述类型的数据时,DataTemplateSelector交换到特定的DataTemplate和选择器,而且似乎回滚/重置旧模板中的值。为什么是这样?

编辑:,我发现这些值是重新审核的,因为我有一个附加的属性,称为Prop,而在它的OnPropertyChangedCallback中,它通知我在DataTemplates之间的交换时,它的值为null。您可以在下面的代码中看到附加属性。

有人能帮我找出DataTemplateSelector交换机制背后的情况吗?

下面是对代码的更深层次的解释:

代码语言:javascript
复制
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之间交换,还有一个模板。正如我提到的,我有三种类型,stringintand one more,我不想吃。他们的DataTemplates叫做textDataTemplatenumericDataTemplate,还有那个。:)

代码语言:javascript
复制
<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;
    }
  }
}

ContentControl和XAML如下所示:

代码语言:javascript
复制
<Button Click="OnClick" Content="Click Me"/>


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

这就是textDataTemplate的相貌。

代码语言:javascript
复制
<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,只是只允许数字。

Prop是我来自AttProperties class of type stringattached propertyProp就在这三个DataTemplate的某个地方。在Prop上面的是一个TextBox,但它也可能是一个Labelmarkupextension只是一个“返回Hello"。这个扩展只是为了测试如何创建一个自定义的标记扩展。延期没什么大不了的。它不应该与DataTemplates的交换有很大关系。

再解释一次我的问题。交换似乎是重置/回滚我的旧模板。我从textDataTemplate交换到numericDataTemplate,并且textDataTemplate的支持被设置为null,但是之前的值是"Hello“。

为什么会发生这种事?使用tiggers似乎也有相同的行为。一旦一个Trigger不再有效,它就回滚使用的值。DataTemplateSelector是否使用与Triggers相同的机制?

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-28 19:32:17

如果您在数字模板中使用双向绑定,并且它只接受类似Double的内容,则可以将值设置为number。但是没有人能确定没有看到完整的代码。有可能你自己的代码做错了什么。为了更好地理解事物,创建来自ContentControl的自己的控件,并在示例中使用它。然后重写控制方法OnContentxxxChanged,在那里插入断点并调试应用程序。你应该明白,你的数据和模板选择器是怎么回事。当应用程序在断点上停止时,请仔细检查所有值并查看堆栈跟踪。要调试绑定,可以插入IValueConverters,这将为您在代码中提供位置,您可以在其中检查值。

我真的建议你先做最简单的工作,然后再去做一些更复杂的事情,比如有双向绑定的文本框,以及一些你在问题中没有显示的控件属性。下面是TextBlocks的工作版本:

代码语言:javascript
复制
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:

代码语言:javascript
复制
    <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。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15544366

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档