C# 使用datatemplates转换项目源

C# 使用datatemplates转换项目源,c#,wpf,xaml,mvvm,data-binding,C#,Wpf,Xaml,Mvvm,Data Binding,假设我有一个ItemsControl,用于渲染viewModels列表的按钮 <ItemsControl ItemsSource="{Binding PageViewModelTypes}"> <ItemsControl.ItemTemplate> <DataTemplate> <Button Content="{Binding Name}"

假设我有一个
ItemsControl
,用于渲染viewModels列表的按钮

  <ItemsControl ItemsSource="{Binding PageViewModelTypes}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding Name}" 
                        CommandParameter="{Binding }" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

是否有任何方法可以将视图中的
ItemsControl
PageViewModelTypes
替换为相应的模板类型?

将按钮内容绑定到项目内容,您的模板将解析为实际类型:

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Button Content="{Binding}" 
                CommandParameter="{Binding }" />
    </DataTemplate>
</ItemsControl.ItemTemplate>

不幸的是,你的问题一点也不清楚。符合您提供的模糊描述的最常见场景是使用与该类型对应的
DataTemplate
显示
ItemsControl
中的每个项目

让我们称之为
选项A

但是声明:

PageViewModelTypes
替换为视图中
ItemsControl
的相应模板类型

…可以理解为您希望控件使用完全不同的数据源。也就是说,您希望有选择地为
ItemsSource
属性选择不同的值

让我们称之为选项B

后来,在评论中,你被问到:

是否希望在用户单击相关按钮时显示模板

…你回答“是”!尽管这与上述两种行为完全不同

让我们称之为选项C

也许我们可以鼓励您提供急需的澄清。但要做到这一点,从最简单、最常见的场景开始似乎最有成效。下面是一个实现
选项A
的代码示例:

XAML:

<Window x:Class="TestSO28429768ButtonTemplate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestSO28429768ButtonTemplate"
        Title="MainWindow" Height="350" Width="525">

  <Window.Resources>
    <local:ColorToBrushConverter x:Key="colorToBrushConverter1"/>
    <local:BaseViewModelCollection x:Key="itemsCollection">
      <local:StringViewModel Text="Foo"/>
      <local:StringViewModel Text="Bar"/>
      <local:ColorViewModel Color="Yellow"/>
      <local:ColorViewModel Color="LightBlue"/>  
    </local:BaseViewModelCollection>

    <DataTemplate DataType="{x:Type local:StringViewModel}">
      <TextBlock Text="{Binding Text}"/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:ColorViewModel}">
      <Rectangle Width="50" Height="25"
                 Fill="{Binding Path=Color, Converter={StaticResource colorToBrushConverter1}}" />
    </DataTemplate>
  </Window.Resources>

  <Grid>
    <ItemsControl ItemsSource="{StaticResource itemsCollection}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Button Content="{Binding}"/>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
  </Grid>
</Window>
class BaseViewModelCollection : List<BaseViewModel> { }

class BaseViewModel { }

class StringViewModel : BaseViewModel
{
    public string Text { get; set; }
}

class ColorViewModel : BaseViewModel
{
    public Color Color { get; set; }
}

class ColorToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new SolidColorBrush((Color)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

C#:

<Window x:Class="TestSO28429768ButtonTemplate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestSO28429768ButtonTemplate"
        Title="MainWindow" Height="350" Width="525">

  <Window.Resources>
    <local:ColorToBrushConverter x:Key="colorToBrushConverter1"/>
    <local:BaseViewModelCollection x:Key="itemsCollection">
      <local:StringViewModel Text="Foo"/>
      <local:StringViewModel Text="Bar"/>
      <local:ColorViewModel Color="Yellow"/>
      <local:ColorViewModel Color="LightBlue"/>  
    </local:BaseViewModelCollection>

    <DataTemplate DataType="{x:Type local:StringViewModel}">
      <TextBlock Text="{Binding Text}"/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:ColorViewModel}">
      <Rectangle Width="50" Height="25"
                 Fill="{Binding Path=Color, Converter={StaticResource colorToBrushConverter1}}" />
    </DataTemplate>
  </Window.Resources>

  <Grid>
    <ItemsControl ItemsSource="{StaticResource itemsCollection}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Button Content="{Binding}"/>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
  </Grid>
</Window>
class BaseViewModelCollection : List<BaseViewModel> { }

class BaseViewModel { }

class StringViewModel : BaseViewModel
{
    public string Text { get; set; }
}

class ColorViewModel : BaseViewModel
{
    public Color Color { get; set; }
}

class ColorToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new SolidColorBrush((Color)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}
class BaseViewModelCollection:列表{}
类BaseViewModel{}
类StringViewModel:BaseViewModel
{
公共字符串文本{get;set;}
}
类ColorViewModel:BaseViewModel
{
公共颜色{get;set;}
}
类别ColorToBrushConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
返回新的SolidColorBrush((颜色)值);
}
公共对象转换回(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
}
如您所见,
ItemsControl
使用默认面板
StackPanel
显示
按钮
实例。每个
按钮的
内容
都绑定到
ItemsSource
集合中的相应项,该列表包含
StringViewModel
类和
ColorViewModel
类各两个

通过窗口资源中定义的模板,按钮的内容呈现者使用与每种类型的视图模型关联的
DataTemplate
。与
StringViewModel
对应的项获取该类型的模板,即显示视图模型文本的
TextBlock
。同样,与
ColorViewModel
实例相对应的项将获得一个模板,该模板显示一个填充了视图模型颜色的矩形

如果上述内容不能准确回答您的问题(很可能不是),请编辑您的问题以澄清您的问题:

  • 如果上述内容很接近,但不是您想要的,请将上述内容作为参考,并解释您想要做的事情有何不同
  • 如果以上内容与您想要的内容无关,请忽略它。但一定要明确你真正想要什么,并使用精确的术语。例如,如果确实要用不同的集合替换
    ItemsSource
    ,那么说要替换
    PageViewModelTypes
    集合是有意义的。但如果不是,不要使用一个似乎完全是这样说的短语
当然,如果
选项B
选项C
与您试图做的事情更接近,请继续并将其作为您澄清的参考


最后,请查看非常有用的页面和。他们有很多关于你如何用一种让别人容易理解你的意思的方式来表达自己的信息

如果已为PageViewModelTypes集合的每种类型创建了datatemplate,那么是否需要为ItemsControl定义项模板?如果您不定义模板,那么xaml将自动从参考资料部分选择相应的模板。如果出于任何原因这不起作用,您可以设置。我仍然希望将ViewModels呈现为按钮,而不是视图,这就是为什么我不能删除
数据模板
@Clemens在这种情况下如何使用ItemTemplateSelector?我无法理解…那么您想在用户单击相关按钮时显示模板吗?这对我不起作用,
OtherViewModel
仍然没有被
OtherView
typesTry替换以引用模板作为ItemsControl的资源或将其添加到App.xamlI不知道您的意思。你能解释一下,我该怎么做吗?:-)我假设问题在于,无法从items控件访问包含视图的DataTemplates的资源字典。仅出于测试目的,将它们放在app.xaml中最常见的位置这也可以起作用:。。。