如何在XAML中包装Datagrid列

时间:2016-06-11 02:22:23

标签: c# wpf xaml datagrid

对不起,我不知道如何更好地解释这个,但我想在数据网格中包装列。

我不是试图将文本包装在datagrid列中,而是包含datagrid的实际列。

我搜索了网络,我已经通过Adam Nathan浏览了WPF 4.5,很可能是因为我没有能力正确描述我想要做的事情,搜索只提出了文本包装。老实说,我不知道如何处理这个问题。

这是我对datagrid的XAML

<DataGrid Name="InfoCountTextBlock" ColumnWidth="100" Grid.Row="3" Grid.ColumnSpan="4" Margin="5" GridLinesVisibility="None" AlternationCount="2">
                    <DataGrid.RowStyle>
                        <Style TargetType="DataGridRow">
                            <Setter Property="Background" Value="White"/>
                            <Setter Property="FontWeight" Value="Normal"/>
                            <Style.Triggers>
                                <Trigger Property="AlternationIndex" Value="1">
                                    <Setter Property="Background" Value="#ddebf7"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#338fff"/>
                                    <Setter Property="Foreground" Value="White"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </DataGrid.RowStyle>
                </DataGrid>

这就是背后的代码,

foreach (string infoOption in InfoOptions)
            {
                infoCount.Add(
                    new InfoOption {
                        Info = infoOption,
                        Instances = filteredSelection.Count(staff => staff.Info_Data == infoOption)
                    }
                );
            }

            InfoCountTextBlock.ItemsSource = infoCount;

这是为了说明我想要实现的目标。 就像现在一样。

enter image description here

这就是我想要实现的,我希望将数据保存在一个数据网格中,因为我可能最终将这些数据连接到DataBase。所以任意地,当数据超过5行时,它会移动到下一个列块,依此类推。

enter image description here

1 个答案:

答案 0 :(得分:1)

右。现在我有一些时间,我实现了它。以下是步骤:

首先,我将定义样本数据类型和一些示例数据,以帮助在设计器内部直观地显示事物,而不必每次都运行它。由于您已经定义了数据类型,因此不需要执行此步骤。只是照顾一件事。我们的控件需要访问名为RowNumber的属性来决定每个元素的行/列。这应该只是一个int类型属性,显示集合中元素的行索引。

public class FiveRowData
{
  public int RowNumber { get; set; }
  public string Column1 { get; set; }
  public string Column2 { get; set; }
}

public class FiveRowList : List<FiveRowData>
{
}

接下来,将一个示例xml数据文件(Add New Item&gt; Resource Dictionary)添加到项目中。这也不是必需的,仅用于设计时支持。将以下示例数据粘贴到文件中:

<YourProject:FiveRowList xmlns:YourProject="clr-namespace:YourProject" Capacity="37">
  <YourProject:FiveRowData RowNumber="1" Column1="Content 1" Column2="Item 1" />
  <YourProject:FiveRowData RowNumber="2" Column1="Content 2" Column2="Item 2" />
  <YourProject:FiveRowData RowNumber="3" Column1="Content 3" Column2="Item 3" />
  <YourProject:FiveRowData RowNumber="4" Column1="Content 4" Column2="Item 4" />
  <YourProject:FiveRowData RowNumber="5" Column1="Content 5" Column2="Item 5" />
  <YourProject:FiveRowData RowNumber="6" Column1="Content 6" Column2="Item 6" />
  <YourProject:FiveRowData RowNumber="7" Column1="Content 7" Column2="Item 7" />
  <YourProject:FiveRowData RowNumber="8" Column1="Content 8" Column2="Item 8" />
  <YourProject:FiveRowData RowNumber="9" Column1="Content 9" Column2="Item 9" />
  <YourProject:FiveRowData RowNumber="10" Column1="Content 10" Column2="Item 10" />
  <YourProject:FiveRowData RowNumber="11" Column1="Content 11" Column2="Item 11" />
  <YourProject:FiveRowData RowNumber="12" Column1="Content 12" Column2="Item 12" />
  <YourProject:FiveRowData RowNumber="13" Column1="Content 13" Column2="Item 13" />
  <YourProject:FiveRowData RowNumber="14" Column1="Content 14" Column2="Item 14" />
  <YourProject:FiveRowData RowNumber="15" Column1="Content 15" Column2="Item 15" />
  <YourProject:FiveRowData RowNumber="16" Column1="Content 16" Column2="Item 16" />
  <YourProject:FiveRowData RowNumber="17" Column1="Content 17" Column2="Item 17" />
</YourProject:FiveRowList>

现在实际工作。在WPF项目中添加新的UserControl。将其命名为FiveRowWrapper(或任何您想要的,但请注意在以下代码中重命名)。转到XAML并使用以下代码替换现有代码:

<ItemsControl x:Class="FiveRowWrapper" 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:YourProject"
  xmlns:syswin="clr-namespace:System.Windows;assembly=PresentationFramework"
  mc:Ignorable="d" 
  d:DesignHeight="180" d:DesignWidth="600" 
  d:DataContext="{d:DesignData Source=FiveRowListSampleData.xaml}"
  ItemsSource="{Binding}">

  <ItemsControl.Resources>
    <local:ItemsCountToColCountConverter x:Key="ItemsCountToColCountConverter" />
    <local:FiveRowToRowNumberConverter x:Key="FiveRowToRowNumberConverter" />
    <local:FiveRowToColNumberConverter x:Key="FiveRowToColNumberConverter" />
  </ItemsControl.Resources>

  <ItemsControl.ItemTemplate>
    <DataTemplate DataType="local:FiveRowData">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Column1}" Margin="10" />
        <TextBlock Text="{Binding Column2}" Margin="10" />
      </StackPanel>
    </DataTemplate>
  </ItemsControl.ItemTemplate>

  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <Grid local:GridHelpers.RowCount="5" 
        local:GridHelpers.ColumnCount="{Binding Count, Converter={StaticResource ItemsCountToColCountConverter}}" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.ItemContainerStyle>
    <Style TargetType="{x:Type ContentPresenter}">
      <Setter Property="Grid.Row" Value="{Binding RowNumber, Converter={StaticResource FiveRowToRowNumberConverter}}" />
      <Setter Property="Grid.Column" Value="{Binding RowNumber, Converter={StaticResource FiveRowToColNumberConverter}}" />
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

有几点要详述。我们使用ItemsControl作为其面板使用Grid。这将作为我们各个项目的整体容器。这些项目将依次使用上面定义的ItemTemplate包含StackPanelTextBlockColumn1来显示每个项目的属性。对于我的示例课程,我使用了Column2ItemTemplate属性,但您可以使用您的属性,甚至可以通过在此处定义自己的ItemContainerStyle以您想要的任何方式自定义单个项目的外观。底部的Grid.Row属性负责绑定每个项目的Grid.ColumnGrid属性,从而将项目放入主Grid内的适当单元格中。

上面的XAML代码还有另外两件事需要解释。首先,我们需要确定Grid中的列数,这可以简单地通过将项目数除以5来计算。但问题是由于GridHelpers的设计,我们不能将列数绑定到属性,并需要通过附加属性间接处理。

在项目中添加一个新类,并将其命名为public class GridHelpers { public static readonly DependencyProperty ColumnCountProperty = DependencyProperty.RegisterAttached("ColumnCount", typeof(int), typeof(GridHelpers), new PropertyMetadata(-1, ColumnCountChanged)); public static int GetColumnCount(DependencyObject obj) { return obj.GetValue(ColumnCountProperty); } public static void SetColumnCount(DependencyObject obj, int value) { obj.SetValue(ColumnCountProperty, value); } public static void ColumnCountChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { if (!(obj is Grid) || (int)e.NewValue < 0) return; Grid grid = (Grid)obj; grid.ColumnDefinitions.Clear(); for (int i = 0; i <= (int)e.NewValue - 1; i++) { grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); } } } (感谢Rachel's helpful answer)。用以下内容替换此文件的内容:

Grid

如您所见,此类将附加属性添加到GridLength.Auto,使用该属性可以动态定义列数。我在这里使用public class ItemsCountToColCountConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (int)Math.Ceiling((int)value / 5f); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class FiveRowToRowNumberConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return ((int)value - 1) % 5f; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class FiveRowToColNumberConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (int)Math.Floor(((int)value - 1) / 5f); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } ,但是如果你想要大小相等的列,你也可以使用固定大小的列。

最后,我们需要以下3个转换器:

  1. 元素数量与列数(将元素数除以5,取上限)
  2. RowNumber to Row(模5)
  3. RowNumber to Column(除以5,取消楼层)
  4. 这是3个转换器的代码。在项目的任何位置定义它们:

    ScrollViewer

    上述工作的最终输出在我的WPF设计器中如下所示:

    enter image description here

    最后,当您向集合中添加更多项目时,控件将水平扩展。您应该将此控件放在stroke-dasharray内以处理该情况。

    我将背景着色和其他较小的活动作为练习。