C# 如何在XAML WPF窗口中拥有动态元素

C# 如何在XAML WPF窗口中拥有动态元素,c#,wpf,xaml,mvvm,user-controls,C#,Wpf,Xaml,Mvvm,User Controls,我有一个MVVMWPF应用程序,可以在其中为纸牌游戏显示卡片。我只是在屏幕上显示它们,一行4张牌,因为一个可观察的集合中有多少张牌。但是,这些卡都是从一个基类继承的不同类型的卡。作为一个用户控件,每种卡类型都有自己的完全不同的视图。因此,根据我的经验,我知道我可以将ItemSource属性绑定到我的可观察集合,但是如何根据ItemSource中的项目类型指定使用某些用户控件?我的理论是,我可以加载每个卡的所有用户控件,并根据卡的类型在转换器中打开或关闭每个控件的可见性,但这听起来效率极低。有人知

我有一个MVVMWPF应用程序,可以在其中为纸牌游戏显示卡片。我只是在屏幕上显示它们,一行4张牌,因为一个可观察的集合中有多少张牌。但是,这些卡都是从一个基类继承的不同类型的卡。作为一个用户控件,每种卡类型都有自己的完全不同的视图。因此,根据我的经验,我知道我可以将ItemSource属性绑定到我的可观察集合,但是如何根据ItemSource中的项目类型指定使用某些用户控件?我的理论是,我可以加载每个卡的所有用户控件,并根据卡的类型在转换器中打开或关闭每个控件的可见性,但这听起来效率极低。有人知道吗?

创建一个
ResourceDictionary
,用于映射UI(即将视图模型映射到模型)并注册它

XAML


然后将可观察集合更改为
可观察集合
,所选视图将显示派生类视图。

创建一个
资源字典
,用于映射UI(即将视图模型映射到模型)并注册它

XAML

然后将可观察集合更改为
可观察集合
,所选视图将显示您要查找的派生类视图。

。例如,假设您有以下类:

公共类MyViewModel
{
公共列表数据项{get;}
=新列表()
{
new AgeInfo(){Age=25},
新名称信息(){Name=13}
};
}
公共抽象类PersonInfo
{
}
公共类AgeInfo:PersonInfo
{
公共整数{get;set;}
}
公共类名称信息:PersonInfo
{
公共int名称{get;set;}
}
您可以使用ItemsControl(或ListBox、ListView等)根据项目的数据类型显示每个项目:


姓名:
年龄:
数据模板的放置位置由您决定,但只要它位于控件的资源层次结构中,就可以使用它。

您正在寻找的。例如,假设您有以下类:

公共类MyViewModel
{
公共列表数据项{get;}
=新列表()
{
new AgeInfo(){Age=25},
新名称信息(){Name=13}
};
}
公共抽象类PersonInfo
{
}
公共类AgeInfo:PersonInfo
{
公共整数{get;set;}
}
公共类名称信息:PersonInfo
{
公共int名称{get;set;}
}
您可以使用ItemsControl(或ListBox、ListView等)根据项目的数据类型显示每个项目:


姓名:
年龄:

数据模板的放置位置由您决定,但只要它位于控件的资源层次结构中,就可以使用它。

您为每种卡类型声明一个。或者,如果这些卡都是相同的类类型,但在属性中指定了它们的类型,则您可以使用。您可以为每种卡类型声明一个。或者,如果这些卡片都是相同的类类型,但在属性中指定了它们的类型,那么您可以使用它们。这似乎太过分了。他们不需要在自己的ResourceDictionary中,即使他们这样做了,你也不需要在代码中合并它,你可以将它添加到应用程序xaml中。嗨,马克,当然你是对的,解决方案只需要是“将ViewModel与视图匹配”,但我仍然认为最优雅的,有序和可维护的解决方案就是我的答案。感谢您对这个答案的投入!虽然我确实喜欢这个解决方案的简单性,但我无权让这个项目创建/处理资源字典。这有点奇怪,但是团队中的每个成员都有特定的角色,他们可以做特定的事情,而创建一个全球资源字典是我无法完成的,这似乎太过分了。他们不需要在自己的ResourceDictionary中,即使是这样,您也不需要将其合并到代码中,您也可以将其添加到应用程序xaml中。嗨,当然,您是对的,解决方案只需要“将ViewModel匹配到视图”,但我仍然认为最优雅,有序和可维护的解决方案就是我的答案。感谢您对这个答案的投入!虽然我确实喜欢这个解决方案的简单性,但我无权让这个项目创建/处理资源字典。这有点奇怪,但是团队中的每个成员都有特定的角色,他们可以做特定的事情,而创建一个全局资源字典是我无法完成这个项目的。
<ResourceDictionary .....
                    xmlns:views="clr-namespace:...."
                    xmlns:viewModels="clr-namespace:...."
                    >

    <DataTemplate DataType="{x:Type viewModels:viewModels1}">
        <views:view1 />
    </DataTemplate>

    <DataTemplate DataType="{x:Type viewModels:viewModels2}">
        <views:view2 />
    </DataTemplate>

    ...

</ResourceDictionary>
public static class ViewsMapping
{
    private static bool _isUIMappingRegistered = false;

    public static void Register()
    {
        if (!_isUIMappingRegistered)
        {
            ResourceDictionary MyResourceDictionary = new ResourceDictionary();
            MyResourceDictionary.Source = new Uri(".....", UriKind.Relative);
            Application.Current.Resources.MergedDictionaries.Add(MyResourceDictionary);
            _isUIMappingRegistered = true;
        }
    }
}