我在DataTemplateSelector
内使用ContentControl
。根据3种不同的DataTemplates
,我有3种不同的object types
。当我将content
的{{1}}设置为所提及类型的数据时,ContentControl
会切换到特定的DataTemplateSelector
并且选择器更多似乎回滚/重置旧模板。为什么会这样?
编辑:我发现这些值会被重置,因为我有一个附加属性,而且它的OnPropertyChangedCallback在其内部通知我有关在DataTemplates之间交换时值为null的Prop。您可以在下面的代码中看到附加属性。
有人可以帮助我解决DataTemplate
的交换机制背后发生的事情吗?
以下是对代码的更深入解释:
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
,int
这三种类型,我希望不要提及。他们的and one more
被称为DataTemplates
,textDataTemplate
,还有一个。 :)
numericDataTemplate
<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;
}
}
}
和XAML看起来像这样:
ContentControl
这就是<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
是来自Prop
attached property
AttProperties class
的{{1}}。 type string
位于所有三个DataTemplate中。 Prop
上方Prop
位于TextBox
,但也可能是Label
。 markupextension
只是“返回Hello”。扩展仅用于测试如何创建自定义markupextension。扩展没什么大不了的。交换DataTemplates
时不应该做太多。
再一次解释我的问题。交换似乎是reselts / rollback我的旧模板。我从textDataTemplate交换为numericDataTemplate,而textDataTemplate的Prop则设置为null,但之前的值为“Hello”。
为什么会这样?使用tiggers
似乎是相同的行为。一旦Trigger
不再有效,它就会回滚使用的值。 DataTemplateSelector
是否使用某种与Triggers
相同的机制?
被修改: 附加属性只是一个带有OnPropertyChangedCallback的简单.RegisterAttached。在OnPropertyChangedCallback内部,我认为在交换dataTemplates时prop是null。
答案 0 :(得分: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