【问题标题】:How to Pass Object to ViewModel when its constructing in MVVM?在 MVVM 中构建时如何将对象传递给 ViewModel?
【发布时间】:2014-04-03 01:45:30
【问题描述】:

我有 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>

是的,视图在后面的代码中也有依赖属性

    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''的绑定源。绑定表达式:路径=控制文本;数据项=空;目标元素是“VM”(HashCode=21019086);目标属性是“文本”(类型“字符串”)

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

【问题讨论】:

    标签: c# wpf mvvm properties dependencies


    【解决方案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,因为正如您的错误所说,UserControl 中没有定义ControlText 属性。试试这个:

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

    最后,如果您想从控件外部将数据绑定到控件的ControlText 属性,那么您可以这样做:

    <local:YourUserControl ControlText="{Binding SomeStringProperty}" />
    

    更新>>>

    在使用 MVVM 时,我们通常尝试通过UIElement 将数据从一个数据源传递到另一个数据源。相反,我们更喜欢将数据从一个数据项传递到另一个数据项。您的问题是您正在视图中实例化您的视图模型......相反,在父视图模型中实例化它并传入您想要的任何值,然后将其设置为 outside 的 UserControl.DataContext 属性值 em> 父视图中的控件:

    <local:YourUserControl DataContext="{Binding YourChildViewModelPropertyInParentVM}" />
    

    一旦您在视图模型中拥有正确的值,您就不需要ControlText 属性。

    【讨论】:

    • 我知道,您向我展示的最后一个特征是我在 Writer (UserCntrol) 中创建 Dependency 属性的主要原因。但我想做一些这样的想法:我有字符串属性字符串 s{get; set;} 我创建 Writer (UserControl) 并通过绑定将此字符串传递给创建的用户控件。 现在我想要一个 UserCONtrol 将属性 s 传递给 Viewmodel。所以我试图在 Writer.xaml 这就是通过视图构建 Viewmodel 的重点。属性 s 正在将视图拖到视图模型
    【解决方案2】:

    如果您在 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-23
      • 2011-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-27
      • 2015-01-20
      相关资源
      最近更新 更多