WPF数据网格(或ListView)通过绑定填充,行使用不同的模板

4
我有一个WPF数据网格,通过数据绑定填充。此列表包含不同的列。我有两种类型的行,一种类型包含行中的所有列,另一种类型应跨越所有列中的一列。
有没有一种简单的方法使这成为可能?(也许使用ListView而不是DataGrid?)
我附上了一个屏幕截图,显示它应该是什么样子:
我现在尝试使用Item Template Selector:
我的资源中的模板(这两个模板不正确,但它们仅用于测试!)
    <DataTemplate x:Key="commentTemplate">
        <TextBlock Text="{Binding}"/>
    </DataTemplate>

    <DataTemplate x:Key="normalTemplate">
        <Image Source="{Binding }" />
    </DataTemplate>

    <WPFVarTab:VarTabRowItemTemplateSelector 
        NormalRowsTemplate="{StaticResource normalTemplate}" 
        CommentRowsTemplate="{StaticResource commentTemplate}" 
        x:Key="vartabrowItemTemplateSelector" />

以及我的数据网格:

<DataGrid AutoGenerateColumns="False" Margin="0,22,0,22" 
              Name="dataGrid" Grid.RowSpan="2" CanUserAddRows="True"
              RowBackground="Azure" AlternatingRowBackground="LightSteelBlue"
              ItemTemplateSelector="{StaticResource vartabrowItemTemplateSelector}" >

以及我的模板选择器:

public class VarTabRowItemTemplateSelector : DataTemplateSelector 
{
    public DataTemplate NormalRowsTemplate { get; set; }
    public DataTemplate CommentRowsTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        S7VATRow vRow = item as S7VATRow;
        if (vRow == null || string.IsNullOrEmpty(vRow.Comment))
            return NormalRowsTemplate;
        return CommentRowsTemplate;
    }
}

我在SelectTemplate的第一行放置了一个断点,但从未被调用!
3个回答

0

enter image description here

数据和评论的视图模型。同样适用于空白处。

public abstract class RowViewModelBase
{
    public bool IsSpecial { get; set; }
}

public class EmptySpaceViewModel : RowViewModelBase
{
    public EmptySpaceViewModel() => IsSpecial = true;
}

public class DataViewModel : RowViewModelBase
{
    public DataViewModel(string column1, string column2)
    {
        Column1 = column1;
        Column2 = column2;
    }

    public string Column1 { get; set; }
    public string Column2 { get; set; }
}

public class CommentViewModel : RowViewModelBase
{
    public string Comment { get; }

    public CommentViewModel(string comment)
    {
        Comment = comment;
        IsSpecial = true;
    }
}

模板选择器

public class RowContentSelector : DataTemplateSelector
{
    public DataTemplate EmptyTemplate { get; set; }
    public DataTemplate CommentTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is EmptySpaceViewModel)
            return EmptyTemplate;
        if (item is CommentViewModel)
            return CommentTemplate;
        return base.SelectTemplate(item, container);
    }
}

xaml

<Window
    ...>
    <Window.Resources>
        <DataTemplate x:Key="EmptyRow">
            <Border Height="30" />
        </DataTemplate>
        <DataTemplate x:Key="CommentTempate">
            <TextBlock Foreground="Green" Text="{Binding Comment}" />
        </DataTemplate>
        <local:RowContentSelector
            x:Key="RowContentSelector"
            CommentTemplate="{StaticResource CommentTempate}"
            EmptyTemplate="{StaticResource EmptyRow}" />
    </Window.Resources>

    <DataGrid
        AutoGenerateColumns="False"
        CanUserAddRows="False"
        ItemsSource="{Binding}"
        RowDetailsTemplateSelector="{StaticResource RowContentSelector}"
        RowDetailsVisibilityMode="Visible">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Column1}" Header="column1" />
            <DataGridTextColumn Binding="{Binding Column2}" Header="column2" />
        </DataGrid.Columns>
        <DataGrid.ItemContainerStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridRow}">
                            <Border
                                x:Name="DGR_Border"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                SnapsToDevicePixels="True">
                                <SelectiveScrollingGrid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition Width="*" />
                                    </Grid.ColumnDefinitions>

                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>

                                    <DataGridCellsPresenter
                                        x:Name="cells"
                                        Grid.Column="1"
                                        ItemsPanel="{TemplateBinding ItemsPanel}"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />

                                    <DataGridDetailsPresenter
                                        x:Name="details"
                                        Grid.Row="1"
                                        Grid.Column="1"
                                        SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}}"
                                        Visibility="{TemplateBinding DetailsVisibility}" />

                                    <DataGridRowHeader
                                        x:Name="header"
                                        Grid.RowSpan="2"
                                        SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                        Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Row}}" />
                                </SelectiveScrollingGrid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsSpecial}" Value="True">
                                    <Setter TargetName="cells" Property="Visibility" Value="Collapsed" />
                                    <!--<Setter TargetName="header" Property="Visibility" Value="Collapsed" />-->
                                </DataTrigger>
                                <DataTrigger Binding="{Binding IsSpecial}" Value="False">
                                    <Setter TargetName="details" Property="Visibility" Value="Collapsed" />
                                </DataTrigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.ItemContainerStyle>
    </DataGrid>
</Window>

例子

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new List<RowViewModelBase> {
            new EmptySpaceViewModel(),
            new DataViewModel("aaaa", "bbb"),
            new EmptySpaceViewModel(),
            new DataViewModel("aaaa", "bbb"),
            new CommentViewModel("//comment"),
            new DataViewModel("aaaa", "bbb"),
            new CommentViewModel("//comment"),
            new CommentViewModel("//comment"),
            new DataViewModel("aaaa", "bbb"),
        };
    }
}

当然,如果您有一个备选模板 - 您就不需要模板选择器,可以直接设置模板

<DataGrid.RowDetailsTemplate>
    <DataTemplate>
            <TextBlock Text="{Binding Comment}" />
    </DataTemplate>
</DataGrid.RowDetailsTemplate>

0
使用绑定来打开和关闭数据行的可见性,就像这样。我假设你已经定义了列。
<DataGrid.RowDetailsTemplate>
     <DataTemplate>
     <ContentControl Style="{StaticResource CommentTemplate}" Content="{Binding Comment}" Visibility="{Binding IsCommentVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
    </DataTemplate>
</DataGrid.RowDetailsTemplate>

请查看http://www.wpf-tutorial.com/datagrid-control/details-row/。如果链接失效,以下是行和列详细信息的代码供您参考。

 <Window x:Class="WpfTutorialSamples.DataGrid_control.DataGridDetailsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataGridDetailsSample" Height="200" Width="400">
        <Grid Margin="10">
                <DataGrid Name="dgUsers" AutoGenerateColumns="False">
                        <DataGrid.Columns>
                                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                                <DataGridTextColumn Header="Birthday" Binding="{Binding Birthday}" />
                        </DataGrid.Columns>
                        <DataGrid.RowDetailsTemplate>
                                <DataTemplate>
                                        <TextBlock Text="{Binding Details}" Margin="10" />
                                </DataTemplate>
                        </DataGrid.RowDetailsTemplate>
                </DataGrid>
        </Grid>
</Window>

代码视图模型

using System;
   using System.Collections.Generic;
   using System.Windows;

   namespace WpfTutorialSamples.DataGrid_control
   {
        public partial class DataGridDetailsSample : Window
        {
                public DataGridDetailsSample()
                {
                        InitializeComponent();
                        List<User> users = new List<User>();
                        users.Add(new User() { Id = 1, Name = "John Doe", Birthday = new DateTime(1971, 7, 23) });
                        users.Add(new User() { Id = 2, Name = "Jane Doe", Birthday = new DateTime(1974, 1, 17) });
                        users.Add(new User() { Id = 3, Name = "Sammy Doe", Birthday = new DateTime(1991, 9, 2) });

                        dgUsers.ItemsSource = users;
                }
        }

        public class User
        {
                public int Id { get; set; }

                public string Name { get; set; }

                public DateTime Birthday { get; set; }

                public string Details
                {
                        get
                        {
                                return String.Format("{0} was born on {1} and this is a long description of the person.", this.Name, this.Birthday.ToLongDateString());
                        }
                }
        }
    }

0

有人知道为什么ItemtemplateSelector不起作用吗? - Jochen Kühner
@Jochen:抱歉,我很久没有访问这个网站了。你的问题在此期间解决了吗? - Vlad
不,我现在正在尝试实现一个CustomDataGridCellsPanel! - Jochen Kühner
@Jochen:很奇怪你的SelectTemplate从未被调用。如果你还没有放弃,请给VarTabRowItemTemplateSelector类添加一个构造函数,看看它是否被调用了?(一个空构造函数就可以了。) - Vlad
我会尝试一下,如果可行就会发布!目前我已经在DataGridCellPresenter中尝试了自己的Itemspanel,但是这也不起作用(http://stackoverflow.com/questions/6423001/set-itemspanel-of-a-datagridcellspresenter-via-style-not-working)。 - Jochen Kühner
显示剩余5条评论

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