2010-04-02 49 views
7

我做了一个示例演示VS 2010 RC示例项目,因为在我的生产项目中,我使用MVVM发生同样的错误。ContentTemplateSelector只被称为一次显示总是相同的数据模式

在我的示例演示项目中,我只使用代码隐藏没有第三方的依赖,所以你可以在这里下载演示项目并运行它自己: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; 
    } 
} 

:)

+1

更好的职位代码片段,而不是提供下载,人们很可能不会去下载这个吨。 – 2010-04-02 09:17:29

+1

确定编辑我的初始文章! – msfanboy 2010-04-02 10:43:19

+1

确定经过一番调研后: http://joshsmithonwpf.wordpress.com/2007/03/18/updating-the-ui-when-binding-directly-to-business-objects-that-are-modified/ 像乔什在他的代码评论中说:“...这是必要的,因为WPF绑定系统将忽略 \t \t \t // PropertyChanged通知如果属性返回与之前相同的对象引用...” 我不能返回相同的对象,而不是我必须在按钮事件处理程序中重新创建Person对象,如: ... = new Person(){IsBoy = true,IsGirl = false}等... 然后它的工作。 谢谢乔希! – msfanboy 2010-04-03 10:29:25

回答

5

我喜欢尼尔的解决方案(通过the link you providedJosh's post找到):

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

+0

http://stackoverflow.com/questions/5771362/wpf-how-to-set-the-data-template-trigger-for-content-control – invalidusername 2013-07-30 13:53:40

3

注意:我认为这种方法很笨拙,但可以适用于某些场景。我赞成使用触发器(来自尼尔)的方法,我发布了一个单独的答案。


另一种可能的方法是将ContentTemplateSelectorContent绑定到确定应选择的模板的性质。例如,在这里我有两个不同的工具栏,其基于SourceSystem的值进行选择。我将 Content设置为源系统属性本身。

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

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

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

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

虽然有点正确,但它不允许你*执行内容绑定到**完整对象***,如',同时允许_template选择器观察与content_不同的事物,比如'.IsBoy' vs'.IsGirl就像问题一样。 – quetzalcoatl 2015-04-22 09:28:00