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

时间:2015-03-10 21:00:16

标签: c# wpf mvvm custom-controls

我正在处理多文档查看器(一个带有自定义控件的简单窗口,每个窗口都有一个单独的视图模型)。单击文件名时,会在主窗口中添加用户控件的新实例。用户控件具有依赖项属性,该属性保存文件名的路径,该文件名在其后面的代码隐藏中定义。现在我想知道如何从用户控件获取此属性的值到viewmodel,因此它可以显示实际文档。任何提示?

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

我在主窗口中使用此代码来创建我的用户控件的新实例,其中DocumentSource是我需要访问的依赖属性,如上所述。

修改

以下是视图的(相关)代码和我的控件的viewmodel,特定于我所拥有的依赖属性值捕获问题。

UserControl.xaml.cs

public partial class ToolboxControl : UserControl
{
    public static readonly DependencyProperty DocumentSourceProperty = DependencyProperty.Register("DocumentSource",
        typeof(string), typeof(ToolboxControl), new UIPropertyMetadata(new PropertyChangedCallback(OnDocumentSourceChanged)));

    public ToolboxControl()
    {
        InitializeComponent();
    }

    public string DocumentSource
    {
        get { return (string)GetValue(DocumentSourceProperty); }
        set { SetValue(DocumentSourceProperty, value); }
    }
    private static void OnDocumentSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
    }
}

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;
                    }
            }
        }
    }
  .....        

}

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

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

1 个答案:

答案 0 :(得分:0)

我不确定我是否理解您的问题(或者您了解依赖属性如何工作),因此您可能需要发布更多代码(例如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中公开一个Property。

这里重要的是你将它设为TwoWay绑定,因此UserControll的任何更改都将更新ViewModel中的有界字段。

您的ViewModel:

public class Doc1ViewModel : ViewModelBase {
    private string path;
    public string Path
    {
        get { return path;}
        set { 
            if(path!=value) {
                path = value;
                OnPropertyChanged("Path");
            }
        }
}
}

现在,每次在 UserControl 中分配属性时,ViewModel中的值都会更新。如您所见,Dependency属性由两个属性组成。一个名为static的{​​{1}}依赖项属性和一个名为PathProperty的实例属性。

但是仔细看看它,它根本不是真正的实例属性。它只是使用PathGetValue(它们是从每个UI控件继承的DependencyObject类派生而来)包围Dependency属性的调用。

希望这可以清除Dependency Properties的工作原理,因为很难在没有看到代码的情况下判断出你的方法有什么问题。

简而言之,依赖属性(与附加属性一起)使用TwoWay可绑定属性扩展XAML代码(普通实例属性只能在一个方向上绑定)。