传递给 UserControl 的继承 ViewModel 被视为子 ViewModel
Inherited ViewModel passed to UserControl is treated as child ViewModel
我有一个视图 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>
对于按钮,我有两个 ViewModel:ButtonViewModel
和 ButtonViewModelChild
。
ButtonViewModelChild
继承自 ButtonViewModel
。两者都提供 IsVisible
属性:
ButtonViewModel:
public Visibility IsVisible
{
get
{
return Visibility.Hidden;
}
}
ButtonViewModelChild:
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();
}
}
如果 ButtonViewModel
用作按钮的 DataContext,按钮应该是不可见的;如果使用 ButtonViewModelChild
,按钮应该是可见的。
我假设使用 ButtonViewModel1 作为 DataContext 的按钮获得 ButtonViewModel
,另一个按钮获得 ButtonViewModelChild
。所以第一个按钮将不可见,而第二个按钮会。虽然这两个按钮都是可见的。 WPF在这里做什么?显然,它两次都使用实例的继承视图。有没有办法告诉 WPF 使用 属性 的 return 类型而不是创建的实例类型?
我知道方法隐藏不是最佳实践。我可能会更改设计,但我很好奇为什么结果不如预期。
绑定路径中的 属性 通过反射解析,因此它找到子 class 属性,而不管 ButtonViewModel1 属性 类型。
public ButtonViewModel ButtonViewModel1
{
get { return new ButtonViewModelChild(); } // subclass instance
}
为避免这种情况,您必须 return 来自 getter:
的 ButtonViewModel
实例
public ButtonViewModel ButtonViewModel1
{
get { return new ButtonViewModel(); }
}
您也可以将 属性 声明为 object
,绑定仍然有效:
public object ButtonViewModel1
{
get { return new ButtonViewModelChild(); }
}
除此之外,您通常不应让 UserControl 操作特定的视图模型(从而使其依赖于 viel 模型 class)。相反,您应该在 UserControl class 中声明一个 IsButtonVisible
依赖项 属性,然后像这样绑定它:
<StackPanel>
<Button Visibility="{Binding IsButtonVisible,
RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBlock>My Button</TextBlock>
</Button>
</StackPanel>
用法为:
<local:Button IsButtonVisible="{Binding ButtonViewModel1.IsVisible}" />
我认为问题是你的 getter 中的类型错误,它们都是 return ButtonViewModelChild viewmodel,当你从 ButtonViewModel1 而不是 ButtonViewModelChild 的 return ButtonViewModel 时应该隐藏
我有一个视图 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>
对于按钮,我有两个 ViewModel:ButtonViewModel
和 ButtonViewModelChild
。
ButtonViewModelChild
继承自 ButtonViewModel
。两者都提供 IsVisible
属性:
ButtonViewModel:
public Visibility IsVisible
{
get
{
return Visibility.Hidden;
}
}
ButtonViewModelChild:
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();
}
}
如果 ButtonViewModel
用作按钮的 DataContext,按钮应该是不可见的;如果使用 ButtonViewModelChild
,按钮应该是可见的。
我假设使用 ButtonViewModel1 作为 DataContext 的按钮获得 ButtonViewModel
,另一个按钮获得 ButtonViewModelChild
。所以第一个按钮将不可见,而第二个按钮会。虽然这两个按钮都是可见的。 WPF在这里做什么?显然,它两次都使用实例的继承视图。有没有办法告诉 WPF 使用 属性 的 return 类型而不是创建的实例类型?
我知道方法隐藏不是最佳实践。我可能会更改设计,但我很好奇为什么结果不如预期。
绑定路径中的 属性 通过反射解析,因此它找到子 class 属性,而不管 ButtonViewModel1 属性 类型。
public ButtonViewModel ButtonViewModel1
{
get { return new ButtonViewModelChild(); } // subclass instance
}
为避免这种情况,您必须 return 来自 getter:
的ButtonViewModel
实例
public ButtonViewModel ButtonViewModel1
{
get { return new ButtonViewModel(); }
}
您也可以将 属性 声明为 object
,绑定仍然有效:
public object ButtonViewModel1
{
get { return new ButtonViewModelChild(); }
}
除此之外,您通常不应让 UserControl 操作特定的视图模型(从而使其依赖于 viel 模型 class)。相反,您应该在 UserControl class 中声明一个 IsButtonVisible
依赖项 属性,然后像这样绑定它:
<StackPanel>
<Button Visibility="{Binding IsButtonVisible,
RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBlock>My Button</TextBlock>
</Button>
</StackPanel>
用法为:
<local:Button IsButtonVisible="{Binding ButtonViewModel1.IsVisible}" />
我认为问题是你的 getter 中的类型错误,它们都是 return ButtonViewModelChild viewmodel,当你从 ButtonViewModel1 而不是 ButtonViewModelChild 的 return ButtonViewModel 时应该隐藏