如何在视图中控制从视图模型中获取特定数据?

时间:2014-07-21 10:10:05

标签: c# wpf mvvm

我有多个视图(用户控件),每个视图都有自己的ViewModel。要在它们之间导航,我正在使用按钮。按钮显示来自相应视图模型的图像和文本,还需要列和行(因为有10个视图:10列,每行有不同的行数)。

现在按钮是动态创建 (我为此创建了一个Navigator控件)对于视图模型我有基类来保存文本,图像,列和行。可用的观看次数会有所不同(取决于用户级别和某些设置),这就是我需要控制的原因。

问题:我的控件如何从视图模型中获取数据?

现在我有接口INavigator,在(lol)控件本身中定义。视图模型实现它。我可以反过来,让我的控制知道关于视图模型的。两者都看错了。


有一个Navigator控件,可以说,Items绑定到视图模型列表。它可以将每个视图模型转换为INavigatorViewModelBase(所有页面都通用)以获取特定的视图模型图像,文本,列和行。所以任一视图模型都知道控制(实现INavigator)或控制知道ViewModelBase ..这是一个问题,两个解决方案绑定严格控制和视图模型,这在{{1}中是不好的}。


示意性地 enter image description here

4 个答案:

答案 0 :(得分:3)

您绘制图表的方式回答了您自己的问题,即如何为此构建代码。

你需要的是一个虚拟机(让我们称之为MainVM),其中包含ObservableCollection<VMBase>个其他虚拟机(使用你的基本类型,以便他们都可以幸福地生活在同一个集合中)。 / p>

您的视图需要ItemsControl(绑定到您的ObservableCollection<VMBase>),您只需使用VMBase类型公开的属性为Button指定DataTemplate。在按钮中设置Command属性以呼叫SwitchCommandCommandParameter设置为项目本身(即{Binding .})。

您的视图还需要ContentControl绑定到SelectedVM上可以填充的MainVM媒体资源。

实施SwitchCommand以根据CommandParameter中的值设置SelectedVM属性。

public void ExecuteSwitchCommand(object parameter)
{
   var vmBase = parameter as VMBase;
   if (vmBase != null)
      SelectedVM = vmBase;
}

此处提到的所有属性都应该INotifyPropertyChanged启用,以便View在更改和更新UI时进行注册。

要获取ContentControl的不同UI,请将每种特定VM类型的特定于类型的DataTemplates添加到View的Resources文件中(或者如果您很聪明并且正在构建自定义插件框架,合并资源字典)。

很多人忘了MVVM,重点是View与ViewModel有目的地分离,这意味着你可以为一个ViewModel提供很多视图,这就是它所展示的。

答案 1 :(得分:2)

我觉得将MVVM视为一种自上而下的方法是最容易的...... View了解它的ViewModel,ViewModel知道它的模型,但Model不知道它的ViewModel和ViewModel不知道它的视图。

我还发现了一种最容易使用的View-first开发方法,因为XAML中的UI开发是静态的(必须是)。

我认为很多人都会把每个组件(M,V,VM)独立且可替换的,包括在内,但我和我一起。我们慢慢得出结论,这只会适得其反。

从技术上讲,确定你可以变得非常复杂并使用IoC容器,创建一些将View类型绑定到ViewModel类型的ViewLocator对象,但是......除了更多的混淆之外,究竟是什么让你获益?因为现在你已经失去了设计时间的支持,尤其是在其他方面,它使老实说更难(因为我已经在某一点上完成了这一点);并且绑定到视图中的特定视图模型界面或在运行时创建绑定。为什么会使它复杂化?

This article is a good read,第一个注意:明确谈到了View与ViewModel。希望它能帮助你得出自己的结论。

要直接回答您的问题,我认为让您的ViewModel实现某种类型的INavigator接口可能是理想的。请记住,您的虚拟机是“粘合剂”。在您的视图和模型/业务逻辑之间,它的工作是将业务数据转换为您的视图可以使用的数据,因此它存在于UI和业务层之间。

这就是Messengers and View Services之类的东西,这是ViewModel上的导航器服务可以很好地适应的原因。

答案 2 :(得分:1)

我认为这种设计导致了一种无路可走的局面。

我相信创建一个自定义按钮控件,其中dependency properties绑定图像,行和列实际上为它所驻留的页面提供了一种方式来获取它们的信息;它们是否是动态创建的。

继续这个想法。没有MVVM逻辑应用于自定义控件,该控件包含完成其工作所需的内容,并且通过所提到的依赖项属性。按钮的任何功能都应该通过命令来完成;所有这些都使按钮数据驱动并足够强大,可以在MVVM方法中使用。

  

问题:我的控件如何从视图模型中获取数据?

只有一个viewmodel,它是控件所在的页面。控件只是绑定到最终驻留在该VM上的信息。它是如何实现的,这取决于程序员。如果该按钮将包含状态数据,那么它将从其依赖属性以双向方式绑定回,它将被绑定。

通过将VM保持在按钮之外,并且只有一个VM是分离和维护数据的最佳方式。除非我真的在这里错过了什么......

答案 3 :(得分:1)

在这里和其他人一样,我觉得实际理解你的要求有点难,所以这很普遍。问题标题的答案很简单:Control始终通过绑定从ViewModel获取数据。您将Control的DataContext设置为相应的ViewModel,然后从那里保持ViewModel和Control同步:

如果您向视图添加ItemsControl个按钮,则会向ViewModel添加ObservableCollection<ButtonViewModel>并将ItemsSource的{​​{1}}绑定到此。

如果您允许用户向View动态添加内容,则执行该操作的实际代码将驻留在ViewModel中,例如当用户单击“添加按钮”按钮时,您使用ItemsControl属性调用ViewModel方法,该方法将Command添加到集合中,View将自动反映您的更改。

确实存在无法在ViewModel中专门编码的复杂案例,我发现行为是那里缺少的链接,但是当你向我展示具体案例时我会深入研究。

如果您想获得一个有效的示例,请提供尽可能多的代码,并准确了解它应该做什么。