1

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

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

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

我可以为此目的实现一个接口(以便布尔属性始终具有相同的名称),但这意味着我将在模型中包含一些仅用于视图的代码。或者在 a 中实现接口,ViewModel并且不能DataTemplateSelector在同一个控件中进行多个操作(不为此目的拆分为类)。

只需按名称绑定即可。非常简单的解决方案,但如果您想在多个控件中重用您的模板,则实际上并不能正常工作。如果我有一个UserControl我需要模板的地方,我会选择的解决方案。只需将其作为资源,UserControl并拥有一个简单且可维护的解决方案。只要您不想在多个控件中使用模板,那绝对没有问题。

还有其他我忽略的想法吗?对上面列出的事情有任何意见吗?

用于说明的示例代码

注意:因为我不在办公室,所以我在没有编译器的情况下输入了代码。既然它应该说明这个问题,编译错误等应该没有太大关系

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

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

TemplateSelector我的典型之一

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 where the OP没有得到任何答案,并提出了第四个想法。我想重申这个问题,以获得对我发布的其他想法的一些反馈。

4

0 回答 0