对两个DataGridTemplateColumns中同一对象的两个不同属性使用相同的DataTemplate

时间:2016-12-21 17:24:16

标签: wpf xaml binding datatemplateselector

我在资源中有两个数据模板,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

我的问题是:如何在Binding中设置正确的Path(Name1或Name2)(而不是Name1OrName2,见上文)。谢谢。

1 个答案:

答案 0 :(得分:3)

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

快速回答:这不是XAML的设计方式。您无法参数化Path的{​​{1}}属性。传统的解决方案是为每种情况编写一个模板。如果您可以通过BindingDataGridTemplateColumn属性指定Binding要显示的属性/字段,然后将该值传递给模板,那将是很好的 - 但它不这样做。

I found a likely-looking workaround here,但我不确定相对于复制和粘贴DisplayMemberPath并继续您的生活,其上的投资回报率会很好。

如果模板很复杂,需要考虑维护,你可以这样解决:

XAML资源:

DataTemplate

原始答案

这是一种常见模式:您需要相同<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返回你的选择器。

我想在XAML中使用MarkupExtensionRedGreenTemplateSelectorExtension将模板本身传递给StaticResource,但XAML解析器并不喜欢这个想法。但这很好用。

DynamicResource

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);
    }
}

P.S。 StaticResourceBinding是两个非常不同的类,可以执行非常不同的操作。人们滥用&#34;绑定&#34;意思是&#34;任务&#34;。不是。你根本没有使用任何绑定。