WPF MVVM:ResourceDictionary的配置约定?

时间:2009-04-20 13:40:27

标签: wpf mvvm


更新

在StackOverflow的维基精神中,这是一个更新:

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

我写了一个“快速启动”示例,它使用一些廉价的字符串替换自动映射ViewModels-> Views。如果未找到代表ViewModel的View,则默认为“Under Construction”页面。我正在配音这种方法“WPF MVVM White”,因为这是Joe White的想法。这是一些截图。

第一个图像是“[SomeControlName] ViewModel”具有相应的“[SomeControlName] View”,基于纯命名约定。第二种情况是ModelView没有任何视图来表示它。没有更多的ResourceDictionaries具有长ViewModel来查看映射。现在这是纯粹的命名惯例。

Wpf Mvvm White

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


原帖

周末我在WPF MVVM上阅读了Josh Smith的fantastic MSDN article。它注定是一个邪教经典。

我花了一些时间来探讨要求WPF呈现 ViewModel 的魔力。

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

对于那些错过这种魔力的人,WPF可以通过在ResourceDictionary映射中查找 ViewView 视图并拉出相应的视图。 (向下滚动到Figure 10 Supplying a View )。

立即向我跳出的第一件事是,已经有一个强大的命名惯例:

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

我的问题是:

由于可以以编程方式操作ResourceDictionary,我想知道是否有人设法使用Regex。将整个事情放弃,因此查找是自动的,以及任何新的View / ViewModels是否因其命名约定而得到解决?

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

...还考虑一个启动方法,它使用interop来提取*View$*ViewModel$类名来在代码中构建DataTemplate字典:

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

2 个答案:

答案 0 :(得分: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中编写逻辑,这取决于您的Views和ViewModel是否在同一名称空间中。

答案 1 :(得分:-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文件是包含所有DataTemplates的ResourceDictionary xamls文件