将ContentTemplateSelector绑定到不同的Object然后Content(ContentPresenter)

时间:2012-11-14 01:35:35

标签: c# wpf data-binding

查看我的代码,我意识到我的许多基于DataTemplateSelector的类几乎都做同样的事情,例如检查绑定对象的bool属性。我真的不想拥有一堆几乎同样的对象,但我对我的想法并不完全满意。

我最喜欢的想法是将我需要的对象绑定到模板,并让我的DataTemplateSelector具有可以设置为例如 name 的属性。应该用于选择模板的布尔属性(在我的xaml中实例化选择器时提供名称。 在选择器中,我将使用反射来访问属性。

第二个想法是绑定我的布尔属性,然后在我的模板中使用与祖先DataContext的相对绑定并从那里开始工作。我不喜欢这样,因为它看起来非常直观,也很难维护。

我可以为此目的实现一个接口(这样boolean属性将始终具有相同的名称),但这意味着我将在模型中有一些仅用于视图的代码。或者在ViewModel中实现接口,并且无法让多个DataTemplateSelector在同一个控件中执行此操作(不会为此目的而拆分成类)。

按名称绑定。非常简单的解决方案,但如果您想在多个控件中重用模板,则无法正常工作。我会采用的解决方案,例如有一个UserControl,我需要模板。只需将其作为此UserControl的资源,并提供简单且可维护的解决方案。只要您不想在多个控件中使用模板,那绝对没问题。

还有其他一些我忽略的想法吗?对上面列出的事情有何评论?

澄清的示例代码

注意:由于我不在办公室,因此我在没有编译器的情况下输入代码。由于它应该说明这个问题,编译错误等不应该太重要

我正在谈论的模型的剥离版本:

public class RegisterToRead : IValueNotifyPropertyChanged
{
    ...
    public bool UseName { get {...} set {...} }
}

我的一个典型TemplateSelector s

public class RegisterToReadTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, 
        DependencyObject container)
    {
        if(item != null && item is RegisterToRead)
        {
            RegisterToRead register = (RegisterToRead)item;

            if( register.UseName)
                return element.FindResource("nameSelectionTemplate") as DataTemplate;
            else
                return element.FindResource("manualEntryTemplate") as DataTemplate;
        }
        return null;
    }
}

我不能做什么,但在精神上想要

TemplateSelector,如下所示:

public class BooleanTemplateSelector : DataTemplateSelector
{
    public property DataTemplate TrueTemplate { get; set; }
    public property DataTemplate FalseTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, 
        DependencyObject container)
    {
        if(item != null && item is bool)
        {
            bool value = (bool)item;

            if( value)
                return TrueTemplate;
            else
                return FalseTemplate;
        }
        return null;
    }
}

并像这样使用它,实现上述效果:

<sel:BooleanTemplateSelector
     TrueTemplate="{StaticResource nameSelectionTemplate}" 
     FalseTemplate="{StaticResource manualEntryTemplate}" 
     x:Key="RegisterToReadTemplateSelector" />
<ContentPresenter Content="{Binding SelectedRegister.UseName}" 
    ContentTemplateSelector={StaticResource ResourceKey=RegisterToReadTemplateSelector}"/>

但我不能这样做,因为模板中的DataContext将被设置为UseName属性,这不是我想要的。

这个问题在stackoverflow上有重复:Bind property for ContentTemplateSelector but pass DataContext to template OP没有得到任何答案,并且去了第四个想法。我想重申一下这个问题,以便对我发布的其他想法得到一些反馈。

0 个答案:

没有答案