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

问题描述:

我有一个View MainWindow.xaml,其中包含Button.xaml中定义的两个按钮。该按钮绑定到属性IsVisible,该属性定义按钮是否可见。传递给UserControl的继承ViewModel被视为子ViewModel

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我有两个的ViewModels:ButtonViewModelButtonViewModelChild

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

ButtonViewModel:

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

ButtonViewModelChild:

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

MainWindow.xaml的视图模型包含的属性ButtonViewModel1ButtonViewModel2。这些特性是这样的:如果如果使用ButtonViewModelChildButtonViewModel作为的DataContext的按钮,可见

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

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

的按钮应该是不可见的。

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

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

+0

感谢您的快速回答。那么这两个按钮应该不可见。但他们都是。 – telandor

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

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

为了避免这种情况,你就必须从吸气返回ButtonViewModel实例:

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

你还可申报财产为object,绑定仍然工作:

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

除此之外,你通常不应该让UserControl操作一个n特定的视图模型(从而使其依赖于viel模型类)。相反,你应该申报的用户控件类IsButtonVisible依赖属性,并绑定绑定像这样:

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

用法是:

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

我认为问题类型错误在你的干将,他们都返回ButtonViewModelChild viewmodel,当你从ButtonViewModel1而不是ButtonViewModelChild返回ButtonViewModel它隐藏,因为它应该是

+1

您应该考虑到OP很清楚两个属性都返回一个子类实例。他们觉得ButtonViewModel1属性的返回类型很重要。 – Clemens