C# 如何从其viewmodel访问自定义控件依赖项属性

C# 如何从其viewmodel访问自定义控件依赖项属性,c#,wpf,mvvm,custom-controls,C#,Wpf,Mvvm,Custom Controls,我正在使用一个多文档查看器(一个带有自定义控件的简单窗口,每个窗口都有一个单独的viewmodel)。单击文件名时,用户控件的新实例将添加到主窗口中。用户控件有一个dependency属性,该属性保存文件名的路径,该文件名在其代码隐藏中定义。现在,我对如何从用户控件到viewmodel获取此属性的值感到惊讶,这样它就可以显示实际的文档。有什么提示吗 <ctrl:DocViewerControl x:Key="docviewer" DocumentSource="{Binding S

我正在使用一个多文档查看器(一个带有自定义控件的简单窗口,每个窗口都有一个单独的viewmodel)。单击文件名时,用户控件的新实例将添加到主窗口中。用户控件有一个dependency属性,该属性保存文件名的路径,该文件名在其代码隐藏中定义。现在,我对如何从用户控件到viewmodel获取此属性的值感到惊讶,这样它就可以显示实际的文档。有什么提示吗

    <ctrl:DocViewerControl x:Key="docviewer" DocumentSource="{Binding SelectedItem.Path, ElementName=docList}"/>
PV_ViewModel.cs

public class PV_ViewModel : ObservableObject
{

  .....

    public string DocumentSource
    {
        get { return (String.IsNullOrEmpty(_documentsource)? (_documentsource = @"about:blank") : _documentsource); }
        set { SetField<string>(ref _documentsource, value, "DocumentSource"); }
    }

  .....        

    public PV_ViewModel()
    {
        PropertyChanged += DocumentSourceChanged;
    }

  .....        

    protected void DocumentSourceChanged(object sender, PropertyChangedEventArgs e)
    {
        if (sender != null)
        {
            switch(e.PropertyName)
            {
                case "DocumentSource":
                    {
                        // show the document and whatsoever
                        break;
                    }
            }
        }
    }
  .....        
公共类PV_视图模型:ObserveObject
{
.....
公共字符串文档源
{
获取{return(String.IsNullOrEmpty(_documentsource)?(_documentsource=@“about:blank”):_documentsource);}
set{SetField(ref _documentsource,value,“documentsource”);}
}
.....        
公共PV_视图模型()
{
PropertyChanged+=DocumentSourceChanged;
}
.....        
受保护的void DocumentSourceChanged(对象发送方,PropertyChangedEventArgs e)
{
if(发送方!=null)
{
开关(如PropertyName)
{
案例“DocumentSource”:
{
//显示文档和其他内容
打破
}
}
}
}
.....        
}

viewmodel DocumentSource属性的getter和setter都不能从任何地方访问,尽管MainWindow中的UserControl已使用当前文档路径字符串填充DocumentSourceProperty。(我可以在主应用程序上看到它是当前打开文档的集合)


澄清一下:应用程序解决方案包含MainWindow项目(主视图、一个带有TreeView和UserControl容器的简单窗口)、UserControl项目(希望是)独立应用程序,用于在提供要通过DocumentSource属性显示的文档路径时显示单个文档。

我不确定我是否理解您的问题(或者您是否理解依赖项属性的工作原理),因此您可能需要在后面发布更多的代码(例如DI)

通常,您的
DocViewerControl
如下所示

public abstract class DocViewerControl : UserControl
{
    public string Path
    {
        get { return (string)GetValue(PathProperty); }
        set { SetValue(PathProperty, value); }
    }

    public static readonly DependencyProperty PathProperty =
        DependencyProperty.Register("Path", typeof(string), typeof(DocViewerControl), new PropertyMetadata(string.Empty));

}
这将在控件的XAML中公开属性

这里很重要的一点是,要使其具有双向绑定,因此对UserControll的任何更改都将更新ViewModel中的有界字段

您的ViewModel:

public class Doc1ViewModel : ViewModelBase {
    private string path;
    public string Path
    {
        get { return path;}
        set { 
            if(path!=value) {
                path = value;
                OnPropertyChanged("Path");
            }
        }
}
}
现在,每次在用户控件中分配属性时,ViewModel中的值都将更新。如您所见,依赖项属性由两个属性组成。一个
静态
依赖项属性称为
路径属性
,另一个实例属性称为
路径

但仔细看一下,它根本不是一个真正的实例属性。它只是通过使用
GetValue
SetValue
(它们派生自每个UI控件继承的DependencyObject类)围绕Dependency属性包装调用

希望这能澄清依赖性属性是如何工作的,因为在没有看到使用的代码的情况下很难判断您的方法有什么问题


简言之,依赖属性(连同附加属性)使用双向可绑定属性(普通实例属性只能在一个方向上绑定)扩展XAML代码.

对不起,我迟到了一点。正如你所看到的,我已经完成了你上面提到的。举个例子,我想知道的是“TextBox如何知道它的Text属性在XAML中被设置为一个值,以及它如何在代码隐藏中捕获该值?”(当然,假设TextBox控件使用MVVM模式!)
public class Doc1ViewModel : ViewModelBase {
    private string path;
    public string Path
    {
        get { return path;}
        set { 
            if(path!=value) {
                path = value;
                OnPropertyChanged("Path");
            }
        }
}
}