0

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

MainWindow.xaml:

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

按钮.xaml:

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

对于按钮,我有两个 ViewModel:ButtonViewModelButtonViewModelChild.

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

按钮视图模型:

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 的按钮得到 a ButtonViewModel,另一个按钮得到 a ButtonViewModelChild。所以第一个按钮将不可见,而第二个按钮将不可见。两个按钮都是可见的。WPF 在这里做什么?显然,它两次都使用了实例的继承视图。有没有办法告诉 WPF 使用属性的返回类型而不是创建的实例类型?

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

4

2 回答 2

1

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

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

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

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

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

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

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

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

用法是:

<local:Button IsButtonVisible="{Binding ButtonViewModel1.IsVisible}" />
于 2017-08-18T07:26:35.393 回答
0

我认为问题是您的吸气剂中的类型错误,它们都返回 ButtonViewModelChild视图模型,当您从 ButtonViewModel1 而不是 ButtonViewModelChild 返回 ButtonViewModel 时,它应该是隐藏的

于 2017-08-18T10:22:28.077 回答