ContentTemplateSelector вызывается только один раз, показывая всегда одну и ту же таблицу данных
Я сделал пример демонстрационного проекта VS 2010 RC, потому что в моем производственном проекте у меня та же ошибка при использовании MVVM.
В моем демонстрационном демонстрационном проекте я использую только Code-behind без сторонних зависимостей, поэтому вы можете скачать демонстрационный проект здесь и запустить его для себя: http://www.sendspace.com/file/mwx7wv
Теперь к проблеме: когда я нажимаю кнопку "девочки / мальчики", она должна переключать табличку с данными, не так ли?
Что я не прав?
ОК, я предлагаю здесь также фрагмент кода:
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:
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;
}
}
:)
3 ответа
Мне нравится решение Нейла (найденное в сообщении Джоша по предоставленной вами ссылке):
<DataTemplate DataType="{x:Type local:MyType}">
<ContentPresenter Content="{Binding}" Name="cp" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsRunning}" Value="True">
<Setter TargetName="cp" Property="ContentTemplate" Value="{StaticResource StopTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsRunning}" Value="False">
<Setter TargetName="cp" Property="ContentTemplate" Value="{StaticResource StartTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Изменить: я не мог заставить вышеуказанный код работать, но это работает с использованием стиля:
<DataTrigger Binding="{Binding Path=SourceSystem.SourceSystemName}"
Value="mysite.com">
<Setter Property="ContentControl.ContentTemplate"
Value="{StaticResource mysiteToolbar}" />
<DataTrigger Binding="{Binding Path=SourceSystem.SourceSystemName}"
Value="mysite2.com">
<Setter Property="ContentControl.ContentTemplate"
Value="{StaticResource mysiteToolbar2}" />
</Style.Triggers>
Примечание: я думаю, что этот метод довольно неуклюжий, но может работать для некоторых сценариев. Я предпочитаю метод использования триггера (от Нейла), который я разместил в качестве отдельного ответа.
Другой возможный способ - связать Content
из ContentTemplateSelector
в свойство, которое определяет шаблон, который должен быть выбран. Например, здесь у меня есть две разные панели инструментов, выбранные в зависимости от значения SourceSystem
, Я установил Content
быть самой собственностью системы источников.
<ContentControl ContentTemplateSelector="{StaticResource toolbarTemplateSelector}"
DataContext="{Binding}" Content="{Binding SourceSystem}" />
Селектор шаблонов просто смотрит на исходную систему и возвращает необходимый шаблон.
Если шаблону необходим доступ к текстовому тексту элемента управления, просто используйте привязку элемента, чтобы установить его.
<UserControl.Resources>
<DataTemplate x:Key="toolbar1">
<views:OrdersToolbar1View Margin="0,5,0,0"
DataContext="{Binding ElementName=control,Path=DataContext}"/>
</DataTemplate>
<DataTemplate x:Key="toolbar2">
<views:OrdersToolbar2View Margin="0,5,0,0"
DataContext="{Binding ElementName=control,Path=DataContext}"/>
</DataTemplate>
</UserControl.Resources>
Используйте этот метод для пользовательского селектора контента:
private void ReloadContent()
{
MainContentControl.ContentTemplate = MainContentControl.ContentTemplateSelector.SelectTemplate(null, MainContentControl);
}
В xaml:
<ContentControl Content="{Binding}" x:Name="MainContentControl">
<ContentControl.ContentTemplateSelector >
<templateSelectors:MainViewContentControlTemplateSelector>
<templateSelectors:MainViewContentControlTemplateSelector.BoysTemplate>
<DataTemplate>
<local:UserControl1 />
</DataTemplate>
</templateSelectors:MainViewContentControlTemplateSelector.BoysTemplate>
<templateSelectors:MainViewContentControlTemplateSelector.GirlsTemplate>
<DataTemplate>
<local:UserControl2 />
</DataTemplate>
</templateSelectors:MainViewContentControlTemplateSelector.GirlsTemplate>
</ContentControl>
И селектор:
public class MainViewContentControlTemplateSelector : DataTemplateSelector
{
public DataTemplate BoysTemplate{ get; set; }
public DataTemplate GirlsTemplate{ get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var contentControl = container.GetVisualParent<ContentControl>();
if (contentControl == null)
{
return BoysTemplate;
}
if (//Condition)
{
return GirlsTemplate;
}
return BoysTemplate;
}