如何使用MVVM调用用户控件方法?

4
我正在一个WPF项目中工作,使用MVVM模式。
我创建了一个用户控件(也在WPF中),并希望在我的项目中使用它。现在,我的问题是我在用户控件中有一个方法需要从我的View Model中调用,但我不知道如何绑定到控件内部的方法。
如果我使用代码后台,显然没有问题,因为我直接引用了我的控件,所以我可以执行“mycontrol.MyMethod();”,但是,这样做会违反MVVM模式的逻辑。
我尝试在我的用户控件中使用Dependency Property,并在我的项目xaml中绑定到它,但它没有起作用,编译器说属性找不到或不可序列化。
所以,如果有人能分享一些关于如何实现这个的信息,我将不胜感激。
根据我的理解,您有一个视图,即所有GUI,然后您有一个模型,即所有逻辑,然后您有一个视图模型,它类似于用于将视图与模型绑定的中间层,对吗?
以这种方式开发了我的项目,但我遇到了一个问题,我需要一个自定义控件,一个记住用户输入内容的文本框,当用户开始键入时,如果有以该字母开头的单词,则显示这些单词作为建议,就像Google一样。
这个TextBox作为搜索过滤器使用;所以我创建了一个用户控件来实现这个,我添加了一个方法到我的用户控件中,允许任何使用我的控件的应用程序添加项目到一个保存用户输入的所有字符串的内部数组中。
我创建了一个用户控件,因为我找不到任何表现出我想要的行为的控件。
所以我的问题是当我将我的用户控件添加到主项目时,因为我需要某种方式能够调用添加项目到内部数组的方法,但也许我正在以错误的方式处理它,如果您中的任何人有更好的想法,我将不胜感激。
3个回答

1
你不应该从 ViewModel 中调用 View 方法,反之亦然。
在你的 ViewModel 上创建一个属性(ObservableCollection?),它将具有 CollectionChanged 事件,如有需要,请订阅它以监视更改。
当您在 ViewModel 中向集合添加项时,GUI 将相应更新(顺便说一下,您必须在 GUI 线程上执行 Add() 操作)。
如果您需要更改列表中的当前位置,则有相应的集合(CollectionViewSource 等)。
如果您确实需要将字符串传递给控件,可以创建一个 DependencyProperty,并将其 OneWay 绑定到 ViewModel 的属性。当您设置值时,它将调用 DependencyProperty 的 PropertyChangedCallback。

0

在 ViewModel 中调用 View 中的内容是不合适的,因为这会破坏模型。

如果你想要调用用户控件中的方法只是为了处理 UI 相关的事情,那么我认为从 View 中调用并没有什么问题 - 因为 View 的 cs 和 View 的 xaml 在模型中处于同一“空间”。你不必过分追求让 View 的 cs 文件更加简洁。


我说过我想从ViewModel中调用方法,因为它距离View最近,但你是对的,按照Model逻辑,我应该从Model中调用方法,但问题仍然存在,你怎样才能从Model中调用用户控件内部的方法呢?我需要使用的方法是将项添加到用户控件中的内部数组中... - Vic
@Vic 我觉得你误解了Amaca的建议。当Amaca说“Model”时,他/她指的是MVVM模式。你绝对不应该需要直接从Model引用View。也许你可以编辑你的答案,加上更多关于你场景的细节,这样别人就可以为你提出建议了。很可能是你创建了一个控件,其实你不需要这么做(创建一个真正的控件应该是相当罕见的),我们可以帮助你更好地解决这个问题。 - Anderson Imes

0
为什么用户控件的使用者需要维护控件的内部数组呢?这似乎暴露了一个不必要的实现细节。
为什么不将该数组简单地作为依赖属性(以及一个IEnumerable<string>ObservableCollection<string>)呢?然后,您可以在视图模型中创建相应的属性并将其绑定到控件。这也使得控件更加灵活多变。

是的,你说得完全正确,在那种方式下更容易。然而,我按照你建议的尝试了一下,但当我在视图模型中添加或删除相应属性的项时,我的用户控件中的依赖属性从未更新。 - Vic
@Vic:听起来像是INotifyPropertyChanged问题或类似的东西。这是基本的绑定通知内容。Robert的建议应该有效...你只需要在绑定上挖掘一下。这篇文章将帮助你调试绑定:http://bea.stollnitz.com/blog/?p=52 - Anderson Imes
我找到了两种解决这个问题的方法,第一种是将我的目标属性设置为依赖属性,因此视图模型类必须从DependencyObject子类化。另一种方法是将我的目标属性设置为普通属性,但在set{}中必须添加一行“base.RaisePropertyChanged(“your_property_name”);”,并且视图模型类必须从ObservableObject子类化。非常感谢您的评论,否则我就无法解决这个问题了。 - Vic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接