ContentTemplateSelector 仅被调用一次,始终显示相同的数据模板
我制作了一个示例演示 VS 2010 RC 示例项目,因为在我的生产项目中,我使用 MVVM 遇到了相同的错误。
在我的示例演示项目中,我仅使用代码隐藏,没有第 3 方依赖项,因此您可以在此处下载演示项目并自行运行:http://www.sendspace.com/file/mwx7wv
现在问题是:当我单击“女孩/男孩”按钮时,它应该切换数据模板,不是吗?
我有什么错吗?
好的,我也在这里提供一个代码片段:
MainWindow.cs 后面的代码:
namespace ContentTemplateSelectorDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Person person;
public MainWindow()
{
InitializeComponent();
person = new Person(){ Gender = "xxx"};
person.IsBoy = true;
ContentGrid.DataContext = person;
}
private void btnBoys_Click(object sender, RoutedEventArgs e)
{
person.IsBoy = true;
person.IsGirl = false;
this.ContentGrid.DataContext = person;
}
private void btnGirls_Click(object sender, RoutedEventArgs e)
{
person.IsGirl = true;
person.IsBoy = false;
this.ContentGrid.DataContext = person;
}
}
}
XAML MainWindow.xaml:
<Window x:Class="ContentTemplateSelectorDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentTemplateSelectorDemo"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="girlsViewTemplate">
<local:UserControl1 />
</DataTemplate>
<DataTemplate x:Key="boysViewTemplate" >
<local:UserControl2 />
</DataTemplate>
<local:PersonDataTemplateSelector x:Key="PersonSelector" />
</Window.Resources>
<Grid x:Name="ContentGrid" >
<StackPanel>
<Button Name="btnGirls" Click="btnGirls_Click">Switch Girls</Button>
<Button Name="btnBoys" Click="btnBoys_Click">Switch Boys</Button>
<ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource ResourceKey=PersonSelector}" />
</StackPanel>
</Grid>
</Window>
DataTemplateSelector 类:
public class PersonDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item,DependencyObject container)
{
if (item is Person)
{
Person person = item as Person;
Window window = Application.Current.MainWindow;
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode( window))
return null;
if (person.IsBoy)
return window.FindResource("boysViewTemplate") as DataTemplate;
if (person.IsGirl)
return window.FindResource("girlsViewTemplate") as DataTemplate;
}
return null;
}
}
:)
I have made a sample demo VS 2010 RC sample project, because in my production project I have the same error using MVVM.
In my sample demo project I use only Code-behind without 3rd party dependencies so you can download the demo project here and run it for yourself: http://www.sendspace.com/file/mwx7wv
Now to the problem: When I click the girls/boys button it should switch the datatemplate, not?
What do I wrong?
OK I offer here a code snippet too:
Code-Behind MainWindow.cs:
namespace ContentTemplateSelectorDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Person person;
public MainWindow()
{
InitializeComponent();
person = new Person(){ Gender = "xxx"};
person.IsBoy = true;
ContentGrid.DataContext = person;
}
private void btnBoys_Click(object sender, RoutedEventArgs e)
{
person.IsBoy = true;
person.IsGirl = false;
this.ContentGrid.DataContext = person;
}
private void btnGirls_Click(object sender, RoutedEventArgs e)
{
person.IsGirl = true;
person.IsBoy = false;
this.ContentGrid.DataContext = person;
}
}
}
XAML MainWindow.xaml:
<Window x:Class="ContentTemplateSelectorDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentTemplateSelectorDemo"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="girlsViewTemplate">
<local:UserControl1 />
</DataTemplate>
<DataTemplate x:Key="boysViewTemplate" >
<local:UserControl2 />
</DataTemplate>
<local:PersonDataTemplateSelector x:Key="PersonSelector" />
</Window.Resources>
<Grid x:Name="ContentGrid" >
<StackPanel>
<Button Name="btnGirls" Click="btnGirls_Click">Switch Girls</Button>
<Button Name="btnBoys" Click="btnBoys_Click">Switch Boys</Button>
<ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource ResourceKey=PersonSelector}" />
</StackPanel>
</Grid>
</Window>
DataTemplateSelector class:
public class PersonDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item,DependencyObject container)
{
if (item is Person)
{
Person person = item as Person;
Window window = Application.Current.MainWindow;
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode( window))
return null;
if (person.IsBoy)
return window.FindResource("boysViewTemplate") as DataTemplate;
if (person.IsGirl)
return window.FindResource("girlsViewTemplate") as DataTemplate;
}
return null;
}
}
:)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我喜欢尼尔的解决方案(位于 Josh 的帖子,来自 您提供的链接):
编辑: 我实际上无法让上面的代码工作,但这可以使用以下样式:
I like Neil's solution (found on Josh's post via the link you provided):
Edit: I couldn't actually get the above code to work, but this works using a style:
注意:我认为这个方法相当笨拙,但可以用于某些场景。我喜欢使用触发器(来自尼尔)的方法,我将其作为单独的答案发布。
另一种可能的方法是将
ContentTemplateSelector
的Content
绑定到确定应选择的模板的属性。例如,我根据SourceSystem
的值选择了两个不同的工具栏。我设置了Content
是源系统属性本身。模板选择器只是查看源系统并返回必要的模板。
如果模板需要访问控件的数据上下文,只需使用元素绑定来设置它。
Note: I think this method is quite clumsy, but could work for some scenarios. I favor the method of using a trigger (from Neil) that I posted as a separate answer.
Another possible way is to bind the
Content
of theContentTemplateSelector
to the property that determines the template that should be selected. For instance here I have two different toolbars chosen based upon the value ofSourceSystem
. I set theContent
to be the sourcesystem property itself.The template selector simply looks at the source system and returns the necessary template.
If the template needs access to the datacontext of the control, just use element binding to set it.
使用此方法自定义内容选择器:
在 xaml 中:
和选择器:
Use this method for custom Content Selector:
In xaml:
And Selector :