如何从基类的ObserveableCollection显示子类的属性? [关闭]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从基类的ObserveableCollection显示子类的属性? [关闭]相关的知识,希望对你有一定的参考价值。

我正在构建一个WPF应用程序,它只是团队成员编辑xml的UI。我的视图模型设置正常运行,直到我遇到这个问题。

假设我有一个模型“动物”,其中“狗”和“鸟”继承了它。

在我的viewmodel中,我有属性

public ObservableCollection<AnimalViewModel> Animals {get; set;}

在我看来,我在列表视图中显示每只动物,但对于鸟类,我希望有一个“CanFly”(企鹅和诸如此类)的复选框。我怎么能设置我的viewmodel和绑定来做到这一点?

以下是我当前设置的示例。

//MODELS
public class Animal
{
    public string Name;
}

public class Dog:Animal
{
    public string Breed;
}

public class Bird:Animal
{
    public bool CanFly;
}

//VIEWMODELS
//PropertyChanged.Fody nuget package
[AddINotifyPropertyChangedInterface]
public class BaseViewModel: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
}

public class AnimalDataVM:BaseViewModel
{
    public ObservableCollection<AnimalVM> Animals{get;set;}
}

public class AnimalVM
{
    private Animal animal;
    public AnimalVM(Animal _animal)
    {
        animal = _animal;
    }

    public string Name
    {
        get
        {
            return animal.Name;
        }
        set
        {
            animal.Name = value;
        }
    }
}

public class BirdVM
{
    private Bird bird;
    public BirdVM(Bird _bird)
    {
        bird = _bird;
    }

    public string Name
    {
        get
        {
            return bird.Name;
        }
        set
        {
            bird.Name = value;
        }
    }

    public bool CanFly
    {
        get
        {
            return bird.CanFly;
        }
        set
        {
            bird.CanFly = value;
        }
    }
}
答案

第一种选择是使用DataTemplate。但这要求你在ViewModel中有不同的课程。然而,它非常有效且易于实施:

<ListView Name="MyListview">
    <ListView.Resources>
        <DataTemplate DataType="{x:Type local:AnimalViewModel}">
            <TextBlock Text="Animal"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:DogViewModel}">
            <TextBlock Text="Dog"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:BirdViewModel}">
            <StackPanel Orientation="Horizontal">
                <CheckBox Content="Can fly"/>
                <TextBlock Text="Bird"/>
            </StackPanel>
        </DataTemplate>
    </ListView.Resources>
</ListView>

如果你的ViewModel不能有不同的类型,那么你应该使用Style DataTrigger和你的类属性:

<ListView Name="MyListview">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox Content="Can fly">
                    <CheckBox.Style>
                        <Style TargetType="CheckBox">
                            <Setter Property="Visibility" Value="Collapsed"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsBird}" Value="True">
                                    <Setter Property="Visibility" Value="Visible"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </CheckBox.Style>
                </CheckBox>
                <TextBlock Text="Anything"/>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

以上是关于如何从基类的ObserveableCollection显示子类的属性? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何从基类实例中找出子类?

如何从基类调用派生类方法?

如何使用 C++ 中的模板编程从基类创建派生类?

从基类到派生类的静态转换后找不到成员函数

从基类调用派生类的隐藏(非虚拟)方法

从基类类型的向量访问派生类方法