0

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

问题:对我来说,很明显我需要用适当的动作创建一个UserView和。UserViewModel但是我将如何用 替换Feedback班级中的用户ViewModel?还是有任何其他推荐的方式(比如创建一个将 a 返回的转换器UserViewModelContentPresenter

我正在使用基于 MIX10 上的“构建您自己的 MVVM 框架”演讲的自定义 MVVM 框架(您知道,这样做是为了了解更多关于 MVVM 并保持框架简单和快速的练习)。

4

2 回答 2

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

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

于 2013-05-07T10:58:26.757 回答
1

Caliburn.Micro 是 MIX10 讨论的最终结果,它自动将 ContentControls 绑定到已解析的视图和视图模型

您可以遵循相同的方法:

使子 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>

我假设由于您的框架基于 Rob 的原始演讲,它会根据约定自动绑定属性吗?如果是这样,这里采用相同的方法。ContentControl从文档中可以看出,for 的约定与其他约定略有不同:

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

这个约定的代码是:

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 时通过工厂将数据上下文转换为 VM,但它只会变得一团糟!(除非绝对必要,否则我不太喜欢混合 View-First 和 ViewModel-First 方法的想法)

于 2013-05-07T11:16:11.297 回答