3

我希望能够DataTemplate根据ViewModel.

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

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

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

用户.cs

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

我正在使用ObservableCollection<User>将我的User对象集合保存在视图模型中。我想使用的 2 个数据模板。(现在我只是使用默认图像和文本来查看它的外观)

数据模板

<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,并且我尝试编写一个使用触发器来决定使用哪个模板的数据模板,但我不太清楚我要去哪里错误的。

风格

<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 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 Visibility="{Binding ColumnVisibility}"
  Style="{StaticResource userTemplateStyle}"
  BorderThickness="0"
  Name="itcLoggedInUsers"
  Margin="0"
  ItemsSource="{Binding LoggedInUsers}"
  Grid.Row="1"/>
4

2 回答 2

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; }
}
于 2013-03-20T20:13:41.917 回答
0

这个问题我想多了。如果我需要DataTemplate基于 的boolean属性显示或隐藏元素ViewModel,我可以将元素的可见性绑定到 的属性ViewModel,并使用转换器返回可见性。

解决方案

<DataTemplate DataType="{x:Type md:User}">
  <StackPanel>
    <Image Source="/Images/anon.png" 
           Height="50" 
           Width="50"
           Margin="0,5,0,0"/>
    <TextBlock Text="Firstname" Visibility="{Binding ColumnIsCollapsed, Source={StaticResource ViewModel},Converter={StaticResource InvertBoolVisibility}}"/>
    <TextBlock Text="Lastnamehere" Visibility="{Binding ColumnIsCollapsed, Source={StaticResource ViewModel},Converter={StaticResource InvertBoolVisibility}}"/>
  </StackPanel>
</DataTemplate>

转换器

public class InvertBoolToVisibilityConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    var theBool = (bool)value;
    if (theBool)
      return Visibility.Collapsed;
    else
      return Visibility.Visible;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}
于 2013-03-20T20:56:31.763 回答