更新
在StackOverflow的维基精神中,这是一个更新:
我在下面抨击了Joe White的IValueConverter建议。它就像一个魅力。
我写了一个“快速启动”示例,它使用一些廉价的字符串替换自动映射ViewModels-> Views。如果未找到代表ViewModel的View,则默认为“Under Construction”页面。我正在配音这种方法“WPF MVVM White”,因为这是Joe White的想法。这是一些截图。
第一个图像是“[SomeControlName] ViewModel”具有相应的“[SomeControlName] View”,基于纯命名约定。第二种情况是ModelView没有任何视图来表示它。没有更多的ResourceDictionaries具有长ViewModel来查看映射。现在这是纯粹的命名惯例。
我在这里发布了一个项目下载: 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>", ...)
答案 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文件