代码之家  ›  专栏  ›  技术社区  ›  Adam Rackis

Silverlight中的类型化数据模板

  •  1
  • Adam Rackis  · 技术社区  · 14 年前

    那么你将如何在SL中完成以下工作(作者是Josh Smith,完整链接如下)。简而言之,他是说,如果将TabControl的tab页绑定到ViewModels集合,WPF将通过查找具有适当(匹配)数据类型集的数据模板来了解如何动态显示每个TabControl页。很酷,但我想知道你会怎么做在Silverlight中执行此操作。

    将视图应用于视图模型

    并删除工作空间视图模型 选项卡控件。依靠数据 绑定,的内容属性 TabItem接收 ViewModelBase派生对象到 显示。ViewModelBase不是用户界面 用于渲染自身。默认情况下,在 显示对的调用结果 这显然不是你所需要的, 希望看到我们的类型名称 视图模型类!

    您可以很容易地告诉WPF如何渲染 使用类型化的ViewModel对象 数据模板。类型化数据模板 但它有自己的数据类型 类型类。如果WPF试图呈现一个 对于ViewModel对象,它将 检查资源系统 其数据类型与(或 基类)的类型 使用该模板呈现 选项卡引用的ViewModel对象 项的内容属性。

    MainWindowResources.xaml文件具有 添加到主窗口的资源中 层次结构,这意味着 它包含的资源在 项的内容设置为ViewModel 对象的类型化数据模板 用户控件)来呈现它,如图所示 在图10中。在图10中。

    http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 在图10中。

    1 回复  |  直到 14 年前
        1
  •  1
  •   Brian Genisio    14 年前

    这是一种你可以做到的方法。我以前就用过这样的技术,而且很成功。

    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上的string Name属性而不是类型映射。。。这里的可能性是无穷的和强大的。