7

更新

本着 StackOverflow 的 wiki 精神,这里有一个更新:

我在下面添加了 Joe White 的 IValueConverter 建议。它就像一个魅力。

我已经编写了一个“快速入门”示例,它使用一些廉价的字符串替换来自动映射 ViewModels->Views。如果没有找到代表 ViewModel 的 View,则默认为“正在建设中”页面。我将这种方法称为“WPF MVVM White”,因为这是 Joe White 的想法。这是几个屏幕截图。

第一张图片是“[SomeControlName]ViewModel”的案例,基于纯命名约定,有一个对应的“[SomeControlName]View” 。第二种情况是 ModelView 没有任何视图来表示它。不再有长 ViewModel 到 View 映射的 ResourceDictionaries。现在是纯粹的命名约定。

Wpf Mvvm 白色

我在这里发布了该项目的下载: Mvvm.White.Quickstart.zip


原帖

我在周末阅读了 Josh Smith关于 WPF MVVM的精彩 MSDN 文章。它注定会成为经典。

我花了一段时间才理解要求 WPF 呈现ViewModel的魔力。

这就像说“这是一个类,WPF。去找出使用哪个 UI 来呈现它。”

对于那些错过这个魔法的人,WPF 可以通过在 ResourceDictionary 映射中查找 ModelView 的View拉出相应的View来做到这一点。(向下滚动到图 10 提供视图)。

我立即跳出来的第一件事是已经有一个强大的命名约定:

classNameView  ("View" suffix)
classNameViewModel ("ViewModel" suffix)

我的问题是:

由于ResourceDictionary可以以编程方式进行操作,我想知道是否有人设法使用 Regex.Replace 整个东西,所以查找是自动的,并且任何新的 View/ViewModels 都通过它们的命名约定得到解决?

[编辑] 我想象的是对 ResourceDictionary 的钩子/拦截。

...还考虑在启动时使用互操作提取*View$*ViewModel$类名在代码中构建 DataTemplate 字典的方法:

//build list
foreach ....
    String.Format("<DataTemplate DataType=\"{x:Type vm:{0} }\"><v:{1} /></DataTemplate>", ...)
4

2 回答 2

17

与其编写代码显式地向 ResourceDictionary 添加内容,不如按需生成正确的视图?您可以使用 ValueConverter 执行此操作。

您的资源将如下所示:

<Views:ConventionOverConfigurationConverter x:Key="MyConverter"/>
<DataTemplate DataType="{x:Type ViewModels:ViewModelBase}">
    <ContentControl Content="{Binding Converter={StaticResource MyConverter}}"/>
</DataTemplate>

您仍然需要一个 DataTemplate 资源,但只要您的 ViewModel 都有一个公共基类,您只需要一个 DataTemplate 来处理所有这些。

然后定义值转换器类:

public class ConventionOverConfigurationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        // value is the ViewModel. Based on its GetType(), build a string
        // with the namespace-qualified name of the view class, then:
        return Activator.CreateInstance(Type.GetType(viewName));
    }
    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

您需要做的就是在 Convert 中编写逻辑,这取决于您的 View 和 ViewModel 是否在同一个命名空间中。

于 2009-04-25T16:53:06.530 回答
-1

我决定做几乎相同的事情,所以我将我的 DataTemplates 直接加载到 ResourceDictionary 使用

    private void RegisterResources()
    {
        ResourceDictionary dictionary = new ResourceDictionary();
        dictionary.Source = new Uri("pack://application:,,,/StartupModule;Component/UIResources.xaml");
        Application.Current.Resources.MergedDictionaries.Add(dictionary);
    }

其中 UIResources 文件是一个 ResourceDictionary xamls 文件,其中包含我们所有的 DataTemplates

于 2009-05-01T14:55:03.190 回答