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

时间:2017-08-18 07:14:53

标签: c# wpf inheritance method-hiding

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

MainWindow.xaml:

<local:Button DataContext="{Binding ButtonViewModel1}" />
<local:Button DataContext="{Binding ButtonViewModel2}" />

Button.xaml:

<StackPanel>
    <Button Name="MyButton" Visibility="{Binding IsVisible}">
        <TextBlock>My Button</TextBlock>
    </Button>
</StackPanel>

对于Button,我有两个ViewModel:ButtonViewModelButtonViewModelChild

ButtonViewModelChild继承自ButtonViewModel。两者都提供IsVisible属性:

ButtonViewModel:

public Visibility IsVisible
{
    get
    {
        return Visibility.Hidden;
    }
}

ButtonViewModelChild:

public new Visibility IsVisible
{
    get
    {
        return Visibility.Visible;
    }
}

MainWindow.xaml的ViewModel包含属性ButtonViewModel1ButtonViewModel2。这些属性如下所示:

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

public ButtonViewModelChildButtonViewModel2
{
    get
    {
        return new ButtonViewModelChild();
    }
}

如果ButtonViewModel用作按钮的DataContext,则按钮应该是不可见的,如果使用ButtonViewModelChild则可见。

我假设使用ButtonViewModel1作为DataContext的按钮获得ButtonViewModel而另一个按钮获得ButtonViewModelChild。所以第一个按钮不可见而第二个按钮会显示。这两个按钮都是可见的。 WPF在这做什么?显然,它使用了实例的继承视图。有没有办法告诉WPF使用属性的返回类型而不是创建实例类型?

我知道方法隐藏不是最好的做法。我可能会改变设计,但我很好奇为什么结果不如预期。

2 个答案:

答案 0 :(得分:1)

绑定路径中的属性通过反射解析,因此无论ButtonViewModel1属性类型如何,它都会找到子类属性。

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

为避免这种情况,您必须从getter返回ButtonViewModel个实例:

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

你也可以将属性声明为object,绑定仍然有效:

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

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

<StackPanel>
    <Button Visibility="{Binding IsButtonVisible,
                         RelativeSource={RelativeSource AncestorType=UserControl}}">
        <TextBlock>My Button</TextBlock>
    </Button>
</StackPanel>

用法是:

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

答案 1 :(得分:0)

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