如何将用户控件的属性绑定到MainViewModel并将其datacontext绑定到自己的viewmodel?

时间:2014-12-06 05:21:09

标签: wpf xaml mvvm data-binding

新手绑定问题。我的mainview.xaml调用了多个usercontrol,如:

  <i:InkRichTextView RichText ="{Binding LastNote}" ... />

其中RichText是InkRichTextView.xaml用户控件的代码隐藏中的依赖项属性,LastNote是mainviewmodel的属性。

MainViewModel通过App.xaml中的DataTemplate与MainView隐式关联,如:

 <DataTemplate DataType="{x:Type vm:MainViewModel}">
        <v:MainView/>
 </DataTemplate>

我想将usercontrol InkRichTextView设置为自己的ViewModel,其属性保存在MainViewModel中,如:

<i:InkRichTextView RichText ="{Binding LastNote}" DataContext="{Binding ucFirstControl}" ... />

但是当我这样做时,我的用户控件InkRichTextView丢失了LastNote的上下文(或者在其代码隐藏中丢失了对其依赖项属性的访问权限,或两者兼而有之。)。

如何维护与LastView的MainViewModel属性的绑定,并仍然为用户控件提供单独的DataContext?

(请记住,UserControl在其代码隐藏中定义了依赖项属性。)

感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:1)

通过x:Name属性为MainView命名。然后,对于RichText属性,您可以使用如下绑定:RichText = {Binding ElementName = mainViewName,Path = DataContext.LastNote}

实际上,您可以在Binding的ElementName属性中使用任何具有MainViewModel作为其DataContext的控件。这可能更容易,因为按名称对DataTemplate生成的控件可能很棘手。

以下是一般概念的示例:请注意绑定到ChildName的TextBox如何基于其DataContext隐式执行,而它旁边的TextBox通过parentControl(使用ElementName)绑定到其DataContext上的Name属性。

XAML:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="250">
    <StackPanel x:Name="parentControl" Orientation="Vertical" DataContext="{Binding}">
        <TextBox Text="{Binding Name}"/>
        <StackPanel DataContext="{Binding ChildViewModel}" Margin="10">
            <TextBox Text="{Binding ChildName}"/>
            <TextBox Text="{Binding ElementName=parentControl, Path=DataContext.Name}"/>
        </StackPanel>
    </StackPanel>
</Window>

CS:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }

}

public class PropertyNotifier : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propname)
    {
        var propChanged = PropertyChanged;
        if (propChanged != null)
            propChanged(this, new PropertyChangedEventArgs(propname));
    }
}

public class MainViewModel : PropertyNotifier
{
    private string _name = "MainViewModelProperty";
    private ChildViewModel _childViewModel = new ChildViewModel();

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }

    public ChildViewModel ChildViewModel
    {
        get { return _childViewModel; }
        set
        {
            _childViewModel = value;
            OnPropertyChanged("ChildViewModel");
        }
    }
}

public class ChildViewModel : PropertyNotifier
{
    private string _childName = "ChildViewModelProperty";

    public string ChildName
    {
        get { return _childName; }
        set
        {
            _childName = value;
            OnPropertyChanged("ChildName");
        }
    }
}