C# 传递给UserControl的继承ViewModel被视为子ViewModel

C# 传递给UserControl的继承ViewModel被视为子ViewModel,c#,wpf,inheritance,method-hiding,C#,Wpf,Inheritance,Method Hiding,我有一个视图MainWindow.xaml,其中包含在Button.xaml中定义的两个按钮。按钮绑定到一个属性IsVisible,该属性定义按钮是否可见 MainWindow.xaml: <local:Button DataContext="{Binding ButtonViewModel1}" /> <local:Button DataContext="{Binding ButtonViewModel2}" /> 按钮查看模型儿童: public new Visib

我有一个视图MainWindow.xaml,其中包含在Button.xaml中定义的两个按钮。按钮绑定到一个属性
IsVisible
,该属性定义按钮是否可见

MainWindow.xaml:

<local:Button DataContext="{Binding ButtonViewModel1}" />
<local:Button DataContext="{Binding ButtonViewModel2}" />
按钮查看模型儿童:

public new Visibility IsVisible
{
    get
    {
        return Visibility.Visible;
    }
}
MainWindow.xaml的ViewModel包含一个属性
ButtonViewModel1
ButtonViewModel2
。这些属性如下所示:

public ButtonViewModel ButtonViewModel1
{
    get
    {
        return new ButtonViewModelChild();
    }
}

public ButtonViewModelChildButtonViewModel2
{
    get
    {
        return new ButtonViewModelChild();
    }
}
<StackPanel>
    <Button Visibility="{Binding IsButtonVisible,
                         RelativeSource={RelativeSource AncestorType=UserControl}}">
        <TextBlock>My Button</TextBlock>
    </Button>
</StackPanel>
如果按钮的数据上下文为
ButtonViewModel
,则该按钮应不可见;如果使用
ButtonViewModelChild
,则该按钮应可见

我假设使用ButtonViewModel1作为数据上下文的按钮得到一个
ButtonViewModel
,另一个按钮得到一个
ButtonViewModelChild
。因此,第一个按钮不可见,第二个按钮不可见。但两个按钮都是可见的。WPF在这里做什么?显然,它同时使用实例的继承视图。有没有办法告诉WPF使用属性的返回类型而不是创建的实例类型


我知道方法隐藏不是最佳实践。我可能会更改设计,但我很好奇为什么结果不符合预期。

绑定路径中的属性是通过反射解析的,因此它会找到子类属性,而不管ButtonViewModel1属性类型如何

public ButtonViewModel ButtonViewModel1
{
    get { return new ButtonViewModelChild(); } // subclass instance
}
为了避免这种情况,您必须从getter返回
ButtonViewModel
实例:

public ButtonViewModel ButtonViewModel1
{
    get { return new ButtonViewModel(); }
}
您也可以将属性声明为
对象
,绑定仍然有效:

public object ButtonViewModel1
{
    get { return new ButtonViewModelChild(); }
}

除此之外,通常不应让UserControl操作特定视图模型(从而使其依赖于viel模型类)。相反,您应该在UserControl类中声明一个
IsButtonVisible
dependency属性,并按如下方式绑定它:

public ButtonViewModel ButtonViewModel1
{
    get
    {
        return new ButtonViewModelChild();
    }
}

public ButtonViewModelChildButtonViewModel2
{
    get
    {
        return new ButtonViewModelChild();
    }
}
<StackPanel>
    <Button Visibility="{Binding IsButtonVisible,
                         RelativeSource={RelativeSource AncestorType=UserControl}}">
        <TextBlock>My Button</TextBlock>
    </Button>
</StackPanel>

我的纽扣
用途如下:

<local:Button IsButtonVisible="{Binding ButtonViewModel1.IsVisible}" />


我认为问题是getter中的类型错误,它们都返回ButtonViewModelChildviewmodel,当您从ButtonViewModel1而不是ButtonViewModelChild返回ButtonViewModel时,它应该是隐藏的

谢谢您的快速回答。那么两个按钮都不应该可见。但它们都是。您应该考虑到OP非常清楚这两个属性都返回一个子类实例。他们认为ButtonViewModel1属性的返回类型在某种程度上很重要。