ContentTemplateSelector仅被调用一次,始终显示相同的datatemplate

时间:2010-04-02 09:08:13

标签: wpf datatemplate contenttemplateselector

我制作了一个示例演示VS 2010 RC示例项目,因为在我的生产项目中,我使用MVVM时遇到了同样的错误。

在我的示例演示项目中,我只使用没有第三方依赖关系的代码隐藏,因此您可以在此处下载演示项目并自行运行:http://www.sendspace.com/file/mwx7wv

现在问题:当我点击女孩/男孩按钮时,它应该切换datatemplate,而不是?

我错了什么?

好的我也在这里提供了一个代码片段:

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 个答案:

答案 0 :(得分:5)

我喜欢Neil的解决方案(通过Josh's postthe link you provided找到):

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

  

答案 1 :(得分:3)

注意:我认为这种方法非常笨拙,但可以适用于某些情况。我赞成使用触发器(来自Neil)的方法,我将其作为单独的答案发布。


另一种可能的方法是将Content的{​​{1}}绑定到确定应该选择的模板的属性。例如,我在这里根据ContentTemplateSelector的值选择了两个不同的工具栏。我订了 SourceSystem是sourceystem属性本身。

Content

模板选择器只是查看源系统并返回必要的模板。

如果模板需要访问控件的datacontext,只需使用元素绑定来设置它。

<ContentControl ContentTemplateSelector="{StaticResource toolbarTemplateSelector}" 
                DataContext="{Binding}" Content="{Binding SourceSystem}" />

答案 2 :(得分:-2)

将此方法用于自定义内容选择器:

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