【问题标题】:Silverlight 4 DataTemplate DataTypeSilverlight 4 数据模板数据类型
【发布时间】:2011-03-11 13:51:27
【问题描述】:

Silverlight 4 已经发布,我们似乎又错过了此版本中的 DataTemplate DataType 功能,恕我直言,这对于 MVVM 支持非常关键。对于我的 WPF 应用程序,此时,我非常习惯于将我的视图的 DataTemplates 全局添加到我的 Application.Resources 中,并为我的相应 ViewModels 使用 DataTypes:

即。

<DataTemplate DataType="{x:Type viewModels:myViewModel}">
<views:myView/>
</DataTemplate>

我喜欢这种方法,因为我所有绑定的 ViewModel 都会自动显示正确的内容……当我的视图中有一些 ItemSource 绑定到 ViewModel 集合时尤其有用……例如,这将自动确保每个绑定到 Collection&lt;SomeViewModel&gt; 的 TabControl 中的选项卡显示与 SomeViewModel 关联的视图。

我为 SL 3 尝试的一些事情包括:

  • 创建一个“DataTemplatePresenterContentControl”,在控件加载时自动为内容应用 DataTemplate

  • 使用 TypeConverter,在控件负载上动态应用,沿着可视化树查找数据绑定对象

  • 使用一种样式,在控件负载上动态应用,沿着可视化树向下查找数据绑定对象

但是,这些方法都没有以可接受的方式真正解决我上面提到的情况,这真的很关键。

所以,由于这在 Silverlight 4 中仍然不可能开箱即用,我很想知道是否有人提出了一些合理的替代方案。

谢谢。

【问题讨论】:

    标签: silverlight mvvm silverlight-4.0 datatemplate


    【解决方案1】:

    我在几个商业项目中的做法如下:

    我有一个标准的 IValueConverter

    public class ViewTemplateChooser : IValueConverter
    {
        /// <summary>
        /// Modifies the source data before passing it to the target for display in the UI.
        /// </summary>
        /// <returns>
        /// The value to be passed to the target dependency property.
        /// </returns>
        /// <param name="value">The source data being passed to the target.</param><param name="targetType">The <see cref="T:System.Type"/> of data expected by the target dependency property.</param><param name="parameter">An optional parameter to be used in the converter logic.</param><param name="culture">The culture of the conversion.</param>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is MyViewModel)
            {
                return new MyView { DataContext = value };
            }
    
            return value;
        }
    
        /// <summary>
        /// Modifies the target data before passing it to the source object.  This method is called only in <see cref="F:System.Windows.Data.BindingMode.TwoWay"/> bindings.
        /// </summary>
        /// <returns>
        /// The value to be passed to the source object.
        /// </returns>
        /// <param name="value">The target data being passed to the source.</param><param name="targetType">The <see cref="T:System.Type"/> of data expected by the source object.</param><param name="parameter">An optional parameter to be used in the converter logic.</param><param name="culture">The culture of the conversion.</param>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    转换器需要命名空间注册

    xmlns:Converters="clr-namespace:YourProject.Converters" 
    

    然后您在资源部分中引用转换器:

    <UserControl.Resources>
        <Converters:ViewTemplateChooser x:Key="TemplateChooser" />
    </UserControl.Resources>
    

    最后我使用转换器将 ViewModel 转换为 View,并将 View 的 Datacontext 设置为 ViewModel

    <ContentControl Content="{Binding Workspace, Converter={StaticResource TemplateChooser}}" Margin="5,35,5,5" Grid.Column="1" />
    

    可以修改转换器以实现导航策略,我试图使示例尽可能简单。

    我希望这会有所帮助,您不必走极端 - 或第三方库 - 即可获得所需的内容。

    【讨论】:

      【解决方案2】:

      在 WPF 和 Silverlight 中,我使用 Prism 来执行此操作。我发现根据类型切换视图更加通用。系上它需要一点时间,但一旦系上,可能性就无穷无尽。

      编辑

      我通过将 RegionName 绑定到我的 ViewModel 中的属性来做到这一点(如果需要,可以是 GetType().Name)。然后,我注册名称的类型,它就可以工作了。

      对于 ListBox 之类的东西,我将数据模板设置为:

      <ContentControl Regions:RegionManager.RegionName="{Binding SomeName}" />
      

      如果您不希望 SomeName 出现在您要绑定的对象上,请考虑使用返回类型名称的 ValueConverter:

      <ContentControl Regions:RegionManager.RegionName="{Binding SomeName, Converter={StaticResource ObjectToTypeConverter}}" />
      

      这有帮助吗?

      【讨论】:

      • 我也在使用 Prism 的 RegionManager,但您能否详细说明一下您的具体操作方式?
      • 好的,谢谢。我喜欢这种方法。但它仍然没有解决我上面提到的一个问题;绑定到 IEnumerable - 例如将 TabControl 绑定到 Collection 并期望每个选项卡显示 MyViewForMyViewModelClass UserControl。或者有没有办法调整你的方法来支持它?谢谢。
      • Right.. 在 TabControl 的模板中,包含具有特定于类型的区域名称的 ContentControl。然后,只需注册不同的视图以显示不同类型特定的区域名称。
      • 好的,很酷。我喜欢这个。那么我如何/在哪里调用以向区域注册视图(即 RegionManager.RegisterViewWithRegion)?
      猜你喜欢
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 1970-01-01
      • 2011-10-10
      相关资源
      最近更新 更多