ContentTemplateSelector вызывается только один раз, показывая всегда одну и ту же таблицу данных - PullRequest
7 голосов
/ 02 апреля 2010

Я сделал пример демонстрационного проекта 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 ]

5 голосов
/ 13 октября 2010

Мне нравится решение Нейла (находится на пост Джоша через ссылку, которую вы предоставили ):

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

3 голосов
/ 13 октября 2010

Примечание : я думаю, что этот метод довольно неуклюжий, но может работать для некоторых сценариев.Я предпочитаю метод использования триггера (от Нейла), который я опубликовал в качестве отдельного ответа.


Другой возможный способ - привязать 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>
0 голосов
/ 26 июля 2013

Используйте этот метод для пользовательского селектора контента:

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