在 Avalonia ItemsControl 中根据 ViewModel 类型选择 DataTemplate

Posted

技术标签:

【中文标题】在 Avalonia ItemsControl 中根据 ViewModel 类型选择 DataTemplate【英文标题】:Selecting a DataTemplate based on ViewModel type in Avalonia ItemsControl 【发布时间】:2021-07-03 05:02:51 【问题描述】:

里面有UserControl和ItemsControl,需要根据Items集合元素类型显示不同DataTemplate的item。

以下 TemplateSelector 和基于此答案创建的 XAML (Selecting a DataTemplate based on DataContext property in Avalonia)

    <ItemsControl Items="Binding Items">
        <ItemsControl.DataTemplates>
            <views:ItemsTemplateSelector>
                <DataTemplate x:Key="x:Type itemViewModels:Item1ViewModel">
                    <itemsViews:Item1View/>
                </DataTemplate>
                <DataTemplate x:Key="x:Type itemViewModels:Item2ViewModel">
                    <itemsViews:Item2View/>
                </DataTemplate>
            </views:ItemsTemplateSelector>
        </ItemsControl.DataTemplates>
    </ItemsControl>
        public ItemsViewModel()
        
            this.Items = new ObservableCollection<IItemViewModel>();
            this.Items.Add(new Item1ViewModel("Item1"));
            this.Items.Add(new Item2ViewModel("Item2"));
        

        public ObservableCollection<IitemViewModel> Items  get; 
    public class ItemsTemplateSelector : IDataTemplate
    
        public bool SupportsRecycling => false;

        [Content]
        public Dictionary<Type, IDataTemplate> Templates  get;  = new Dictionary<Type, IDataTemplate>();

        public IControl Build(object data)
        
            var type = data.GetType();
            var template = this.Templates[type];
            var control = template.Build(data);

            return control;
        

        public bool Match(object data)
        
            return data is IItemViewModel;
        
    
    public interface IItemViewModel
    
        string Name  get; 
    
    public class Item1ViewModel : IItemViewModel
    
        public Item1ViewModel (string name)
        
            this.Name = name;
        

        public string Name  get; 
    
<UserControl
  xmlns="https://github.com/avaloniaui"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  x:Class="Desktop.Views.Items.Item1View">

  <TextBlock Text="Binding Name"/>

</UserControl>

在运行时出现异常:

Avalonia.Markup.Xaml.XamlLoadException: '没有为 Desktop.Views.Items.Item1View 找到预编译的 XAML,请确保指定 x:Class 并将您的 XAML 文件包含为 AvaloniaResource'

如果在 ItemsControl 而不是 &lt;itemsViews:Item1View/&gt; 中指定 &lt;TextBlock Text="Binding Name"/&gt;,那么一切正常。但我想将每个项目的标记拆分为具有单独 ViewModel 的单独 XAML 文件。项目可以完全不同。

是否有可能解决这个问题,以便 ItemsControl 将根据 ViewModel 类型选择 DataTemplate?

【问题讨论】:

这看起来与DataGrid 无关,而是您的UserControl 有问题。尝试将UserControl 的实例直接放在一个窗口中,看看它是否首先有效。 【参考方案1】:

为了解决这个问题,我手动编辑了项目文件 *.csproj 添加了 AvaloniaResource 元素

<AvaloniaResource Include="..\Desktop\Views\Items*.xaml">
    <SubType>Designer</SubType>
</AvaloniaResource>

【讨论】:

以上是关于在 Avalonia ItemsControl 中根据 ViewModel 类型选择 DataTemplate的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Avalonia 中绑定颜色

Slider.IsMoveToPointEnabled 在 Avalonia

如何在 Avalonia.ReactiveUI 中使用 Autofac 作为 DI 容器?

Avalonia:如何使用代码为路径中的点设置动画

如何在 Avalonia 应用程序中为 OpenFolderDialog 设置标题?

一起学习Avalonia(十二)