如何将父视图中的参数设置为在用户控件中声明为静态资源的视图模型

时间:2011-11-02 17:17:23

标签: silverlight mvvm view viewmodel

对于view / viewmodel,我有以下(浓缩的)silverlight xaml:

<UserControl x:Class=MyView>    
    <UserControl.Resources>
        <MyViewModel x:Name="MyViewModel"/>
    </UserControl.Resources>

    <Grid DataContext="{Binding Source={StaticResource MyViewModel}}">
<UserControl>

希望大家看起来很熟悉。

但是,我想创建这个相同视图用户控件的2个实例,但是要将参数传递给视图模型,以允许我根据我传递给视图模型的属性略微不同的视图模型数据。类似的东西:

<UserControl x:Class=MyView>    
    <UserControl.Resources>
        <MyViewModel x:Name="MyViewModel" Filter="Some value set at a higher level"/>
    </UserControl.Resources>

    <Grid DataContext="{Binding Source={StaticResource MyViewModel}}">
<UserControl>

问题是我无法在用户控件中硬编码Filter参数,但需要将其设置在更高级别。有没有办法通过绑定从更高的位置获取过滤器参数,以及语法是什么样的。我希望以下内容:

直接来自父母:

<MyView>
    <MyView.ViewModel Filter="All">
</MyView>
<MyView>
    <MyView.ViewModel Filter="Some">
</MyView>

或者从用户控件向上看,例如:

<UserControl.Resources>
    <MyViewModel x:Name="MyViewModel" Filter="{Binding FilterTypeFromDataContextHigherUpTheTree}"/>
</UserControl.Resources>

但我不知道是否可以直接从父级引用静态资源视图模型来设置属性,或者语法是什么样的。

我也不知道是否有更简单的方法可以做到这一点,因为我怀疑我的方法不是很优雅。

真正的问题是我如何将参数传递给静态资源的视图模型

2 个答案:

答案 0 :(得分:1)

虽然可以将ViewModel存储为资源,但我们通常会将ViewModel设置为视图的DataContext。然后,如果有人需要通过 View访问ViewModel ,他们只需将DataContext转换为正确的ViewModel类型并直接访问它的属性。

如果您想要使用过滤器的Binding路线,您有几个选择。如果子控件放在模板(或样式)中的父控件内,则可以将Bnding Soure设置为RelativeSource.TemplatedParent。您也可以使用ElementName,但仅当命名元素位于同一范围内时(在上面的示例中,命名元素必须位于MyView内部。)

我能想到的最后一个选项是在MyView上为过滤器公开DependencyProperty,然后设置ViewModel与该属性的绑定。这将有效地使过滤器冒泡,以便可以在MyView外部访问,但我根本不喜欢这种方法,因为它只是为了将它们传递给ViewModel而向View添加属性。这绝不应该发生。 ViewModel应该始终可以独立于View访问,这就是我建议通过DataContext属性(推断)或通过专门用于ViewModel(显式)的自定义属性公开它的原因。

答案 1 :(得分:0)

我有时会使用我的ViewModel(例如,将它们实例化为资源)。当我这样做时,我的VM会扩展DependencyObject,原因我稍后会详细说明。

我建议您将它们移动到app.xaml并将它们定义为应用程序的资源,作为应用程序的资源,每个人都可以使用它们。那样你就可以

<UserControl
    DataContext="{StaticResource MyViewModel}" />

此外,您可以将ViewModel的属性绑定在一起。这就是我扩展DependencyObject的原因。

当然,这会限制您使用MyViewModel的单个实例,这可能适用于您的情况,也可能不适用。如果它不起作用,我将定义一个包含共享数据的ViewModel,然后通过静态资源绑定到它,就像在“向上看”的例子中一样。