我的理解是Silverlight不支持具有DataType属性的DataTemplates。
如何在SL中完成以下内容(作者是Josh Smith,下面的完整链接)。简而言之,他说如果将TabControl的标签页绑定到ViewModel集合,WPF将通过查找具有相应(匹配)DataType集的DataTemplate来计算如何动态显示每个标签页。很酷,但我想知道你如何(可以?)在Silverlight中做到这一点。
图10中的将视图应用于ViewModel
MainWindowViewModel间接添加 并删除WorkspaceViewModel 来自主窗口的对象 TabControl的。依靠数据 绑定,一个的Content属性 TabItem收到一个 ViewModelBase派生的对象 显示。 ViewModelBase不是UI 元素,所以它没有固有的支持 用于渲染自己。默认情况下,在 WPF是一个非可视对象 显示呼叫结果 TextBlock中的ToString方法。 这显然不是你需要的, 除非您的用户有刻录 希望看到我们的类型名称 ViewModel类!
您可以轻松告诉WPF如何渲染 使用typed的ViewModel对象 的DataTemplates。一个类型化的DataTemplate 没有分配x:Key值 对它,但它确实有它的DataType 属性设置为的实例 输入类。如果WPF尝试渲染一个 你的ViewModel对象,它会 检查是否有资源系统 在范围内有一个类型化的DataTemplate 其DataType与(或a)相同 基类)你的类型 ViewModel对象。如果它找到一个,它 使用该模板来渲染 选项卡引用的ViewModel对象 item的内容属性。
MainWindowResources.xaml文件有 一个ResourceDictionary。那本字典 被添加到主窗口的资源中 层次结构,这意味着 它包含的资源在 窗口的资源范围。当一个标签 item的内容设置为ViewModel object,这是一个类型化的DataTemplate 字典提供一个视图(即,一个 用户控件)渲染它,如图所示 如图10所示。
答案 0 :(得分:1)
这是你可以做到的一种方式。我过去曾经使用过这样的技术,并且取得了很大的成功。
考虑一个非常简单的容器,它将为您创建视图:
public class ViewMapper : ContentControl
{
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property.Name == "DataContext")
WhenDataContextChanges();
}
private void WhenDataContextChanges()
{
if (DataContext == null)
Content = null;
else
Content = ViewFactory.GetView(DataContext.GetType());
}
}
修改强>
因此,您可以使用此控件为您执行映射:
<Border DataContext="{Binding MyViewModel}">
<ViewMapper />
</Border>
结束编辑
请注意,ViewMapper
只是等待数据上下文更改,查找数据类型的相应视图,并创建一个新视图。它依赖于ViewFactory,这是一个非常简单的静态查找,它将类型映射到视图:
public class ViewFactory
{
private static readonly Dictionary<string, Func<UIElement>> _registry = new Dictionary<string, Func<UIElement>>();
private static string Key(Type viewModelType)
{
return viewModelType.FullName;
}
public static void RegisterView(Type viewModelType, Func<UIElement> createView)
{
_registry.Add(Key(viewModelType), createView);
}
public static UIElement GetView(Type viewModelType)
{
var key = Key(viewModelType);
if (!_registry.ContainsKey(key))
return null;
return _registry[key]();
}
}
然后,您只需要在某个地方注册视图映射:
ViewFactory.RegisterView(typeof(SomeViewModel), () => new SomeView());
请注意,ViewFactory可以轻松使用Activator.CreateInstance
而不是使用Func机制。更进一步,你可以使用IoC容器...你总是可以决定通过ViewModel上的字符串Name属性而不是类型来映射...这里的可能性是无穷无尽的。