如何根据ViewModel属性更改自定义类型的DataTemplate?

时间:2013-03-20 19:37:24

标签: c# wpf mvvm

我希望能够根据DataTemplate中的属性更改我的自定义类正在使用的ViewModel

我找不到任何明确的例子,我觉得我对WPFXAML可能不太了解,知道这是否可行。

我的ViewModel属性表示用户是否折叠了应用程序一侧的列。如果该列已折叠,我只想显示每个用户的图像,如果该列已展开,我将在StackPanel中显示图片,名字和姓氏。

我觉得有一些非常基本的东西,我还不明白,我想我正在寻找一个可能会尝试这样的事情的人,或者知道如何以正确的方式做到这一点。

User.cs

public class User
{
  public string ImageFile {get; set;}
  public string FirstName {get; set;}
  public string LastName {get; set;}
}

我正在使用ObservableCollection<User>来保存我在viewmodel中的User个对象集合。 我想要使​​用的2个DataTemplates。 (现在我只是使用默认图像和文本来查看它的外观)

的DataTemplates

<DataTemplate x:Key="UserCollapsed">
  <Image Source="/Images/anon.png" 
         Height="50" 
         Width="50"
         Margin="0,5,0,0"/>
</DataTemplate>

<DataTemplate x:Key="UserExpanded">
  <StackPanel>
    <Image Source="/Images/anon.png" 
           Height="50" 
           Width="50"
           Margin="0,5,0,0"/>
     <TextBlock Text="Firstname"/>
     <TextBlock Text="Lastnamehere"/>
   </StackPanel>
 </DataTemplate>

我试过写一个样式,然后在视图中将它应用到我的ItemsControl,我尝试编写一个使用触发器决定使用哪个模板的datatemplate,但是我无法弄明白我在哪里我出错了。

风格

<Style x:Key="userTemplateStyle" TargetType="ItemsControl">
  <Setter Property="ItemTemplate" Value="{StaticResource UserExpanded}"/>
  <Style.Triggers>
    <DataTrigger Binding="{Binding ColumnIsCollapsed, Source={StaticResource ViewModel}}" Value="True">
      <Setter Property="ItemTemplate" Value="{StaticResource UserCollapsed}"/>
    </DataTrigger>
  </Style.Triggers>
</Style>

当我在XAML中的ItemsControl上添加Style属性时,我得到以下异常。

异常

{"Unable to cast object of type 'MS.Internal.NamedObject' to type 'System.Windows.DataTemplate'."}

我试图用作ItemsControl的ItemTemplate的DataTemplate。 (我觉得这是错误的做法,但无论如何我都试过了)

的DataTemplate

<DataTemplate DataType="{x:Type md:CUser}">
  <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding ColumnIsCollapsed, Source={StaticResource ViewModel}}" Value="True">
      <Setter Property="DataTemplate" Value="{StaticResource UserCollapsed}"/>
    </DataTrigger>
  </DataTemplate.Triggers>
</DataTemplate>

的ItemsControl

<ItemsControl Visibility="{Binding ColumnVisibility}"
  Style="{StaticResource userTemplateStyle}"
  BorderThickness="0"
  Name="itcLoggedInUsers"
  Margin="0"
  ItemsSource="{Binding LoggedInUsers}"
  Grid.Row="1"/>

2 个答案:

答案 0 :(得分:0)

你的代码对我来说很好......

<Window x:Class="WpfApplication8.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfApplication8="clr-namespace:WpfApplication8"
    Title="MainWindow"
    Width="525"
    Height="350">
<Window.Resources>
    <WpfApplication8:ViewModel x:Key="ViewModel" />
    <DataTemplate x:Key="UserCollapsed" />

    <DataTemplate x:Key="UserExpanded">
        <StackPanel Width="200"
                    Height="200"
                    Background="Red">
            <TextBlock Text="Firstname" />
            <TextBlock Text="Lastnamehere" />
        </StackPanel>
    </DataTemplate>
    <Style x:Key="userTemplateStyle" TargetType="ItemsControl">
        <Setter Property="ItemTemplate" Value="{StaticResource UserExpanded}" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding ColumnIsCollapsed, Source={StaticResource ViewModel}}" Value="True">
                <Setter Property="ItemTemplate" Value="{StaticResource UserCollapsed}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid x:Name="grid" DataContext="{StaticResource ViewModel}">
    <ItemsControl Name="itcLoggedInUsers"
                  Grid.Row="1"
                  Margin="0"
                  BorderThickness="0"
                  ItemsSource="{Binding LoggedInUsers}"
                  Style="{StaticResource userTemplateStyle}" />

</Grid>

ViewModel

  public class ViewModel: INotifyPropertyChanged
{
    private bool _columnIsCollapsed;

    public ViewModel()
    {
        ColumnIsCollapsed = false;
        LoggedInUsers = new ObservableCollection<User>();
        LoggedInUsers.Add(new User(){FirstName = "SSSSSS", LastName = "XXXXXX"});
    }
    public bool ColumnIsCollapsed
    {
        get { return _columnIsCollapsed; }
        set
        {
            _columnIsCollapsed = value;
            OnPropertyChanged(new PropertyChangedEventArgs("ColumnIsCollapsed"));
        }
    }

    public ObservableCollection<User> LoggedInUsers { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, e);
    }
}

public class User
{
    public string ImageFile { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

答案 1 :(得分:0)

我过度思考这个问题了。如果我需要根据DataTemplate的{​​{1}}属性显示或隐藏boolean中的元素,我可以将元素的可见性绑定到{{1}上的属性并使用转换器返回可见性。

解决方案

ViewModel

转换器

ViewModel