如何在ViewModel中区分类似的用户控件?

时间:2014-07-24 23:49:53

标签: c# mvvm user-controls windows-phone datacontext

WP8应用。我有xaml页面,有4个相同的UserControls。这一刻看起来非常简单:

<TextBlock Text="name" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <CheckBox Content="chk1" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0,0,0,0"/>
    <CheckBox Content="chk2" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="119,0,0,0"/>

我想将这些数据存储在对象集合中。现在我尝试使用DataContext和ICommand接口。 为每个控件制作12个属性是愚蠢的,所以问题是如何向DataContext发送有关哪一个UserControl正在运行的信息?它将更容易使用例如UserControls的索引或其他东西。

我刚刚学习mvvm ...有什么建议吗?

1 个答案:

答案 0 :(得分:0)

有两种方法可以解决这个问题:数据上下文继承或依赖属性。

第一种方法是利用子控件继承父级DataContext的事实。假设您有一个带有子视图模型的主视图模型。然后,您可以简单地将每个UserControl绑定到适当的视图模型。例如

<local:MyUserControl DataContext="{Binding FirstSubViewModel}" />
<local:MyUserControl DataContext="{Binding SecondSubViewModel}" />

然后,您的用户控件将假设其DataContext具有所需的所有ICommand属性。


第二种方法是让您的用户控件定义ICommand类型的dependency properties

public static readonly DependencyProperty Command1Property = 
    DependencyProperty.Register(
    "Command1", typeof(ICommand),
    typeof(MyUserControl), null
    );
public ICommand Command1
{
    get { return (ICommand)GetValue(Command1Property); }
    set { SetValue(Command1Property, value); }
}

这样,您的控件的使用者将能够使用任何绑定方法绑定命令。例如:

<local:MyUserControl Command1="{Binding chk1Command}" />
<local:MyUserControl Command1="{Binding ElementName=someControl,Path=SomeCommand}" />

这里唯一的技巧是你必须以某种方式从用户控件中绑定到依赖项属性 - 这在Silverlight中很棘手,因为没有RelativeSource=FindAncestor绑定。一种方法是将LayoutRoot的DataContext设置为控件本身。所以,如果你的makrup是这样的:

<UserControl ...>
    <Grid x:Name="LayoutRoot">
        <TextBlock Text="name" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <CheckBox Content="chk1" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0,0,0,0"/>
        <CheckBox Content="chk2" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="119,0,0,0"/>
    </Grid>
</UserControl>

然后在构造函数中,你有:

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        LayoutRoot.DataContext = this;
    }
}