1

我在资源中有两个数据模板和一个 DataTemplateSelector 可供选择:

    <DataGrid.Resources>
        <DataTemplate  x:Key="RedTemplate">
            <TextBlock Text="{Binding **Name1OrName2**}" />                        
       </DataTemplate >

       <DataTemplate x:Key="GreenTemplate">
        ....                
       </DataTemplate>

      <local:MyTemplateSelector x:Key="MyTemplateSelector"
                RedTemplate="{StaticResource RedTemplate}"
                GreenTemplate="{StaticResource GreenTemplate}" />

    </DataGrid.Resources>

这是选择器的代码隐藏:

public class MyTemplateSelector : DataTemplateSelector
    {
        public DataTemplate RedTemplate { get; set; }
        public DataTemplate GreenTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item is RedItem) return RedTemplate;
            else if (item is GreenItem) return GreenTemplate; 
            else return base.SelectTemplate(item, container);                    
        }
    }

只要我将 MyTemplateSelector 用于一个 DataColumn(例如 Name1),它就可以正常工作。但我的 DataGrid 有两个模板列要绑定到两个字符串字段:Name1 和 Name2

<DataGridTemplateColumn CellTemplateSelector="{StaticResource MyTemplateSelector}" > // Should be bound to Name1    
<DataGridTemplateColumn CellTemplateSelector="{StaticResource MyTemplateSelector}" > // Should be bound to Name2

我的问题是:如何在绑定中设置正确的路径(名称 1 或名称 2)(而不是名称 1 或名称 2,见上文)。谢谢你。

4

1 回答 1

3

看起来我最初的答案是由于对问题的误解,并且要求不是关于数据模板选择器,而是如何参数化绑定绑定到的属性,因此您可以对两个不同的属性使用相同的模板.

快速回答:这不是 XAML 设计的使用方式。您不能参数Path化 a 的属性Binding。传统的解决方案是为每个案例编写一个模板。如果您可以通过 a or属性指定DataGridTemplateColumn要显示的属性/字段 a ,然后将该值传递给模板,那就太好了——但它不是那样工作的。BindingDisplayMemberPath

我在这里找到了一个看起来很可能的解决方法,但我不确定它的投资回报率相对于复制和粘贴 aDataTemplate并继续你的生活是否会很好。

如果模板足够复杂以至于需要维护,您可以像这样解决这个问题:

XAML 资源:

<DataTemplate x:Key="RedBaseTemplate">
    <Border BorderBrush="Green" BorderThickness="2" Margin="1">
        <Label x:Name="Text" Background="Red" Content="{Binding}" />
    </Border>
</DataTemplate>
<DataTemplate x:Key="GreenBaseTemplate">
    <Border BorderBrush="Red" BorderThickness="2" Margin="1">
        <Label x:Name="Text" Background="Green" Content="{Binding}" />
    </Border>
</DataTemplate>

<DataTemplate x:Key="RedTemplateA">
    <ContentControl 
        Content="{Binding A}"
        ContentTemplate="{StaticResource RedBaseTemplate}" 
        />
</DataTemplate>
<DataTemplate x:Key="RedTemplateB">
    <ContentControl 
        Content="{Binding B}"
        ContentTemplate="{StaticResource RedBaseTemplate}" 
        />
</DataTemplate>
<DataTemplate x:Key="GreenTemplateA">
    <ContentControl 
        Content="{Binding A}"
        ContentTemplate="{StaticResource GreenBaseTemplate}" 
        />
</DataTemplate>
<DataTemplate x:Key="GreenTemplateB">
    <ContentControl 
        Content="{Binding B}"
        ContentTemplate="{StaticResource GreenBaseTemplate}" 
        />
</DataTemplate>

原始答案

这是一种常见的模式:您需要相同的多个实例DataTemplateSelector(或值转换器,通常是),但具有不同的参数。解决方案是派生自MarkupExtension,因此您可以在使用点使用其自己的唯一参数实例化事物,而不是在其他地方创建一个共享实例作为资源。在这种情况下DataTemplateSelector是一个类而不是一个接口,所以你不能从MarkupExtension. 相反,您编写一个快速MarkupExtension返回您的选择器。

我想将模板本身传递给RedGreenTemplateSelectorExtension使用StaticResourceDynamicResource在 XAML 中,但 XAML 解析器不喜欢这个想法。但这工作得很好。

public class RedGreenTemplateSelectorExtension : MarkupExtension
{
    public Object RedTemplateKey { get; set; }
    public Object GreenTemplateKey { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var redTemplate = new StaticResourceExtension(RedTemplateKey)
            .ProvideValue(serviceProvider) as DataTemplate;

        var greenTemplate = new StaticResourceExtension(GreenTemplateKey)
            .ProvideValue(serviceProvider) as DataTemplate;

        return new RedGreenTemplateSelector() {
            RedTemplate = redTemplate,
            GreenTemplate = greenTemplate
        };
    }
}

public class RedGreenTemplateSelector : DataTemplateSelector
{
    public DataTemplate RedTemplate { get; set; }
    public DataTemplate GreenTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is RedItem)
            return RedTemplate;
        else if (item is GreenItem)
            return GreenTemplate;
        else 
            return base.SelectTemplate(item, container);
    }
}

XAML

<StackPanel>
    <ContentControl
        ContentTemplateSelector="{local:RedGreenTemplateSelector RedTemplateKey=RedTemplate, GreenTemplateKey=GreenTemplate}"
        >
        <local:RedItem/>
    </ContentControl>
    <ContentControl
        ContentTemplateSelector="{local:RedGreenTemplateSelector RedTemplateKey=RedTemplate, GreenTemplateKey=GreenTemplate}"
        >
        <local:GreenItem/>
    </ContentControl>
</StackPanel>

PSStaticResourceBinding是两个非常不同的类,它们做的事情非常不同。人们误用“绑定”来表示“分配”。它不是。您在这里根本没有使用任何绑定。

于 2016-12-21T17:50:53.177 回答