Silverlight 4中的DataTemplate DataType

6
Silverlight 4已经发布,但似乎我们再次错过了DataTemplate DataType功能,这对于MVVM支持来说非常关键。对于我的WPF应用程序,我习惯于将DataTemplates添加到Application.Resources中,并为相应的ViewModels添加DataTypes:
例如:
<DataTemplate DataType="{x:Type viewModels:myViewModel}">
<views:myView/>
</DataTemplate>

我喜欢这种方法,因为所有我的绑定的ViewModel自动显示正确的内容...当我有一些ItemSource在我的视图中绑定到一个ViewModel集合时,特别有用...例如,这将自动确保TabControl中的每个选项卡都与SomeViewModel相关联的视图。

我尝试过的一些SL 3的方法包括:

  • 创建一个“DataTemplatePresenterContentControl”,当控件加载时自动应用Content的DataTemplate

  • 使用TypeConverter,在控件加载时动态应用,沿着可视化树向下查找数据绑定的对象

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

然而,这些方法都没有以可接受的方式解决我上面提到的情况,这是非常关键的。

因此,由于Silverlight 4仍然无法从盒子外实现这一点,我很想知道是否有人已经提出了一些合理的替代方案。

谢谢。

2个回答

8
我在几个商业项目中的做法如下:
我使用标准的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" />

可以修改转换器来实现导航策略,我尽可能地让示例简单。

希望这可以帮助您,您不必走极端或使用第三方库来获得所需内容。


1
在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,但是你能否详细说明一下你是如何做到这一点的呢? - Jeff
是的,谢谢。我喜欢这种方法。但它仍然没有解决我上面提到的一个问题;将绑定到IEnumerable<T> - 例如将TabControl绑定到Collection<MyViewModelClass>并期望每个选项卡显示MyViewForMyViewModelClass UserControl。或者是否有一种方法可以调整您的方法来支持它?谢谢。 - Jeff
在TabControl的模板中,包含一个具有特定类型区域名称的ContentControl。然后,只需注册不同的视图以显示不同的类型特定区域名称。 - Brian Genisio
好的,很棒。那么我该在哪里调用注册视图到区域的方法(例如:RegionManager.RegisterViewWithRegion)呢? - Jeff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接