如何在MVVM中构建对象时将对象传递给ViewModel?

时间:2014-03-02 01:03:34

标签: c# wpf mvvm properties dependencies

我有ViewModel

public class VM: DependencyObject, INotifyPropertyChanged
{
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(VM), new PropertyMetadata(""));

    public int Length 
    { 
        get
        {
            return Text != null ? Text.Length : 0;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

并查看它

<UserControl.DataContext>
    <local:VM Text="{Binding ControlText, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"/>
</UserControl.DataContext>

<StackPanel>
    <TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding Length}"/>
</StackPanel>

是的,view在代码后面还有依赖属性

    public string ControlText
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("ControlText", typeof(string), typeof(Writer), new PropertyMetadata(""));

输出日志出错了

System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.UserControl',AncestorLevel ='1''。 BindingExpression:路径= ControlText;的DataItem = NULL; target元素是'VM'(HashCode = 21019086); target属性是'Text'(类型'String')

当这项技术有效时,我将拥有构建我的viewmodel的工具。 也许有人知道如何将这个视图属性绑定到viewmodel属性或知道技术如何正确地执行它:)

2 个答案:

答案 0 :(得分:1)

你似乎对某些事情感到困惑。如果要将视图模型设置为XAML中的UserControl.DataContext,那没关系,但是没有数据绑定到那里的控件:

<UserControl.DataContext>
    <local:VM  />
</UserControl.DataContext>

接下来,如果视图模型设置为UserControl.DataContext,那么您可以从UserControl中的XAML访问其属性,如下所示:

<StackPanel>
    <TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding Length}"/>
</StackPanel>

现在,如果您想从XAML访问ControlText属性,那么 就是您需要使用RelativeSource Binding的时候。但是,请注意您应该如何使用UserControl引用UserControl的名称/类型和而不是,因为正如您的错误所述,没有定义ControlText属性在UserControl。试试这个:

<StackPanel>
    <TextBox Text="{Binding ControlText, RelativeSource={RelativeSource 
        AncestorType={x:Type local:YourUserControl}} />
    <TextBlock Text="{Binding Length}"/>
</StackPanel>

最后,如果您希望数据绑定到控件的<{1>}属性 outside 控件,那么您可以这样做:

ControlText

更新&gt;&gt;&gt;

使用MVVM时,我们通常尝试将数据从一个数据源通过<local:YourUserControl ControlText="{Binding SomeStringProperty}" /> 传递到另一个数据源。相反,我们更喜欢将数据从一个数据项传递到另一个数据项。您的问题是您在视图中实例化视图模型...而是在父视图模型中实例化它并传入您想要的任何值,然后将其设置为外部的UIElement属性值父视图中的控件:

UserControl.DataContext

在视图模型中获得正确的值后,您就不需要<local:YourUserControl DataContext="{Binding YourChildViewModelPropertyInParentVM}" /> 属性。

答案 1 :(得分:0)

如果在XAML中声明DataContext,它将在XAML加载时初始化。此外,VM不像UserControl那样位于Visual Tree中,因此RelativeSource无法在此处工作。

但是你可以在后面的代码中通过从UserControl的构造函数设置DataContext并在那里自己绑定来实现:

public MainWindow()
{
   InitializeComponent();
   VM viewModel = new VM();
   DataContext = viewModel;
   Binding binding = new Binding("ControlText") { Source = this };
   BindingOperations.SetBinding(viewModel, VM.TextProperty, binding);
}