使用viewmodel替换列表中的对象

时间:2013-05-07 10:50:30

标签: wpf mvvm

场景:我有一个Web服务,可以从我的用户那里获得一些反馈。 Feedback类有一个用户。在ViewModel中,我获得用户发送的反馈的完整列表,并在视图中绑定到它,我希望绑定到列表中的用户以显示谁发送了该反馈。这里没什么不寻常的。但是,我想向用户添加一些控件,以便在您单击它时有一些操作,我想在应用程序的几个位置使用此控件。

问题:对我而言,显然我需要使用适当的操作创建UserViewUserViewModel。但是,如何使用Feedback替换ViewModel班级中的用户?或者是否有任何其他推荐的方法(比如创建一个将UserViewModel返回到ContentPresenter的转换器)?

我正在使用基于MIX10上的“Build Your Own MVVM Framework”演讲的自定义MVVM框架(正如您所知,这样做是为了更多地了解MVVM并保持框架简单快速)。 / p>

2 个答案:

答案 0 :(得分:2)

您需要创建包装器视图模型以包含反馈和用户模型,以便为其添加功能。

这会产生两个类:FeedbackViewModel和UserViewModel。省略财产通知:

 public class UserViewModel {

     public User User { get; set; }
     public ICommand UserAction { get; set; }
     ...
 }

 public class FeedbackViewModel { 

     public UserViewModel User { get; set; }
     public Feedback Feedback { get; set; }
     public ICommand FeedbackAction { get; set; }
     ...
 }

您可以使用某种工厂将反馈集合和用户转换为包装模型对象的视图模型。

答案 1 :(得分:1)

Caliburn.Micro是MIX10谈话的最终结果,它会自动将ContentControl绑定到已解析的视图和viewmodel

您可以采用相同的方法:

使子VM成为父VM的属性...(正如某人已经回答的那样)

public class UserViewModel 
{
    public User User { get; set; }
}

public class FeedbackViewModel 
{ 
    public UserViewModel UserView { get; set; }
}

然后使用ContentControl允许将子VM注入父视图:

<UserControl x:Name="ParentView"> 
    <StackPanel>
       <TextBlock>Some Parent View Content here...</TextBlock>
       <!-- Now the child content: -->
       <ContentControl x:Name="UserView" />
    </StackPanel>
</UserControl>

我假设你已经将你的框架基于Robs原创讲话,它会根据惯例自动绑定属性吗?如果是这样,这里采取相同的方法。 ContentControl的约定与其他文章略有不同,如文档中所示:

  

ContentControl的约定有点有趣。如果我们的项目   绑定到不是值类型而不是字符串,那么我们假设   内容是ViewModel。因此,而不是绑定到内容   我们在其他情况下的属性,我们实际上设置了绑定   使用CM的自定义附加属性:View.Model。这个属性导致   CM的ViewLocator查找视图模型的相应视图   和CM的ViewModelBinder将两者绑定在一起。一旦那样   完成后,我们将视图弹出到ContentControl的Content属性中。   这种单一的约定使得功能强大而简单   ViewModel - 框架中的第一个组合。

此惯例的代码是:

AddElementConvention<ContentControl>(ContentControl.ContentProperty, "DataContext", "Loaded").GetBindableProperty =
            delegate(DependencyObject foundControl) 
            {
                var element = (ContentControl)foundControl;

                if (element.Content is DependencyObject && !OverwriteContent)
                    return null;
#if SILVERLIGHT
                var useViewModel = element.ContentTemplate == null;
#else
                var useViewModel = element.ContentTemplate == null && element.ContentTemplateSelector == null;
#endif
                if (useViewModel) {
                    Log.Info("ViewModel bound on {0}.", element.Name);
                    return View.ModelProperty;
                }

                Log.Info("Content bound on {0}. Template or content was present.", element.Name);
                return ContentControl.ContentProperty;
            };

如您所见,检查Content / ContentTemplate是否为可视元素,如果不是,则假定为VM。然后,可绑定属性作为VM本身(在未设置内容模板的情况下)或内容本身返回。

可能值得一读更多的想法:

http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation

(滚动到准导体部分)

至于在你的应用程序中这样做以将Users替换为ViewModels - 我认为这只是一个漏洞的案例

您可以使用视图优先方法,并可能在解析VM时通过工厂将datacontext转换为VM,但它会变得混乱! (我不喜欢混合View-First和ViewModel-First的想法,绝对需要很多unles)