C# 如何将自定义依赖属性绑定到控件';s视图模型?

C# 如何将自定义依赖属性绑定到控件';s视图模型?,c#,wpf,dependency-properties,C#,Wpf,Dependency Properties,我需要创建一个具有少量输入/输出和大量内部功能的控件。我认为最好的方法是创建依赖属性,以便与其他应用程序部件交互,并使用带有隐藏函数的私有视图模型 这是我的样本: 窗口 <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx

我需要创建一个具有少量输入/输出和大量内部功能的控件。我认为最好的方法是创建
依赖属性
,以便与其他应用程序部件交互,并使用带有隐藏函数的
私有视图模型

这是我的样本:

窗口

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="clr-namespace:WpfApplication1">
<StackPanel>
    <DatePicker x:Name="DatePicker" />
    <app:MyControl DateCtrl="{Binding ElementName=DatePicker, Path=SelectedDate}" />
</StackPanel>
</Window>
视图模型

using System;
using System.ComponentModel;

namespace WpfApplication1
{
    public class ViewModel : INotifyPropertyChanged
    {
        private DateTime _dateVM;
        public DateTime DateVM
        {
            get { return _dateVM; }
            set
            {
                _dateVM = value;
                OnPropertyChanged("DateVM");
            }
        }

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

我需要实现的是将
DatePicker
中选择的
date
传播到
MyControl的
视图模型
。或者,有没有更好的模式可以使用?

您所描述的是一个常见的误解,即所有视图都应该有一个视图模型。但是,对于用作控件的
UserControl
s,只使用它们自己的
dependencProperty
s通常要简单得多(也更合适)

您的方法的问题是您在内部分配了
UserControl-DataContext
,因此无法从控件外部进行设置。解决方案不是在内部设置
DataContext
,而是使用
relativesourcebinding
访问
UserControl dependencProperty
s,如下所示:

<TextBlock Text="{Binding DateCtrl, RelativeSource={RelativeSource 
    AncestorType={x:Type YourLocalPrefix:MyControl}}}" />

DatePicker应该有自己的DatePickerViewModel,它定义SelectedDate属性或dependency属性。您应该定义DatePicker控件的XAML以使用此专用的ViewModel

然后,当您使用该控件时,可以按如下方式设置绑定:

<DatePicker SelectedDate="{Binding Path=DateVM, 
            Mode=TwoWay, 
            UpdateSourceTrigger=PropertyChanged}" />

请注意,DateVM不是日期选择器的属性,而是消费视图模型(或者在本例中是主窗口)上的属性。当选择器打开时,它将默认为DateVM中已设置的日期


另一件事是,你的选择器目前不允许任何拾取-它只是一个文本块

示例中的
DatePicker
表示外部世界,它只知道
DateCtrl
属性,不知道有一些内部视图模型具有
DateVM
TextBlock
仅用于可视化当前示例unset中的内部属性
DateVM
。这将起作用,我可能会这样做,但我担心它会像我以前的
WinForms
应用程序一样,在
控件本身上产生大量代码。另一个缺点是我无法单独测试表示逻辑。然后使用第二个示例,将视图模型作为
依赖属性提供。或者,只需将此
UserControl
中的数据直接绑定到父
UserControl
窗口的视图模型即可。
<TextBlock Text="{Binding DateCtrl, RelativeSource={RelativeSource 
    AncestorType={x:Type YourLocalPrefix:MyControl}}}" />
<TextBlock Text="{Binding YourViewModelProperty.DateVM, RelativeSource={RelativeSource 
    AncestorType={x:Type YourLocalPrefix:MyControl}}}" />
<DatePicker SelectedDate="{Binding Path=DateVM, 
            Mode=TwoWay, 
            UpdateSourceTrigger=PropertyChanged}" />