脱发和MVVM用户控件

时间:2015-01-27 16:33:45

标签: c# wpf mvvm user-controls

我有一个用C#编写的用户控件。 WPF使用MVVM模式。

我想要做的就是在绑定的ViewModel中有一个属性,该属性暴露在控件之外。我希望能够绑定到它,并且我希望对绑定到公开值的控件之外的任何内容拾取属性的任何更改。

这听起来很简单,但它让我拉出我的头发(并没有留下太多的东西)。

我在用户控件中有一个依赖项属性。 ViewModel具有实现INotifyPropertyChanged接口的属性,并正确调用PropertyChanged事件。

一些问题: 1)如何在不破坏MVVM分离的情况下获取对ViewModel属性的更改并将其绑定到依赖属性?到目前为止,我设法做到这一点的唯一方法是在后面的Controls代码中分配ViewModels PropertyChanged事件,这绝对不是MVVM。

2)使用上面的软糖,我可以得到Dependency属性来启动它的PropertyChangedCallback,但是在控件之外绑定到它的任何东西都不会获​​得更改。

必须有一种简单的方法来完成所有这些。请注意,我没有在这里发布任何代码 - 我希望不用我现有的代码来影响答案。而且,无论如何你可能都会嘲笑它......

罗布

好的,澄清 - 代码示例:

后面的用户控制代码:

   public static DependencyProperty NewRepositoryRunProperty = DependencyProperty.Register("NewRepositoryRun", typeof(int?), typeof(GroupTree),
                                                                new FrameworkPropertyMetadata( null, new PropertyChangedCallback(OnNewRepositoryRunChanged)));
    public int? NewRepositoryRun
    {
        get { return (int?)GetValue(NewRepositoryRunProperty); }
        set
        {
            SetValue(NewRepositoryRunProperty, value);
        }
    }

    private static void OnNewRepositoryRunChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.OldValue != e.NewValue)
        {

        }
    }

    public GroupTree()
    {
        InitializeComponent();

        GroupTreeVM vm = new GroupTreeVM();

        this.DataContext = vm;

    }

Viewmodel(GroupTreeVM.cs)

   private int? _NewRepositoryRun;
    public int? NewRepositoryRun
    {
        get
        {
            return _NewRepositoryRun;
        }
        set
        {
            _NewRepositoryRun = value; 
            NotifyPropertyChanged();
        }
    }

2 个答案:

答案 0 :(得分:12)

现在,对于我的每周"不要这样做"回答...

为UserControl创建ViewModel是一种代码味道。

你因为这种气味而遇到了这个问题,这应该表明你做错了。

解决方案是抛弃为UserControl构建的VM。如果它包含业务逻辑,则应将其移动到另一个ViewModel中的适当位置。

您应该将UserControl视为一个更复杂的控件。 TextBox是否有自己的ViewModel?不。您将VM的属性绑定到控件的Text属性,控件在其UI中显示您的文本。

将MVCon中的UserControl想象成这样 - 对于每个模型,您都有一个UserControl,它旨在将该模型中的数据呈现给用户。您可以在任何想要向用户显示该模型的地方使用它。它需要一个按钮吗?在UserControl上公开ICommand属性,并让您的业务逻辑绑定到它。您的业​​务逻辑是否需要知道内部发生的事情?添加路由事件。

通常情况下,在WPF中,如果你发现自己要问为什么做某事很痛,那是因为你不应该这样做。

答案 1 :(得分:0)

也许我误解了,但似乎你在尝试在后面的代码中使用绑定?

public MyUserControl()
{
    InitializeComponent();

    // Set your datacontext.

    var binding = new Binding("SomeVMProperty");
    binding.Source = this.DataContext;

    SetBinding(MyDependencyProperty, binding);
}