プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

WPFのDataGridで列方向のセルを結合する。

この記事は2019年05月04日に投稿しました。

f:id:paveway:20190914064630j:plain

目次

  1. はじめに
  2. WPFのDataGridで列方向のセルを結合する
  3. おわりに

エッセンシャルWPF:Windows Presentation Foundation (Programmer's SELECTION)

エッセンシャルWPF:Windows Presentation Foundation (Programmer's SELECTION)

1. はじめに

こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回は業務で使用しているWPFDataGridで列方向のセルを結合する方法についてです。

目次へ

2. WPFのGridでセルを結合する

WPFDataGridで列方向のセルを結合する方法ですが、以下のサイトを参考にさせてもらいました。

WPF datagrid column heading span more than once column

実装例はほとんど元のコードと同じですが、多少見やすいようにリファクタリングし、コメントを追加しました。
ただDataGridSpannedCellPanelクラスに関してはまだ実装内容について理解中のため、コメントは入れられていません。

実装例

MainWindow.xaml
<Window x:Class="WPFGridColumnSpan.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFGridColumnSpan"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid  x:Name="dataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell">
            <DataGrid.Resources>
                <Style TargetType="DataGridRow">

                    <Setter Property="ItemsPanel" >
                        <Setter.Value>
                            <ItemsPanelTemplate>
                                <local:DataGridSpannedCellPanel ></local:DataGridSpannedCellPanel>
                            </ItemsPanelTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGrid.Resources>
        </DataGrid>
    </Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFGridColumnSpan
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        /**
         * @brief コンストラクタ
         */
        public MainWindow()
        {
            InitializeComponent();

            // データグリッドにカラムを10列追加します。
            for (int i = 0; i < 10; ++i)
            {
                AddColumn(i);
            }

            // string型の行を追加します。
            var stringRows = new string[10];
            stringRows[0] = "列0";
            stringRows[1] = "列1";
            stringRows[2] = "列2";

            // 列3~5をセル結合します。
            var multiSpanText = "結合した列";
            stringRows[3] = multiSpanText;
            stringRows[4] = multiSpanText;
            stringRows[5] = multiSpanText;

            stringRows[6] = "列6";
            stringRows[7] = "列7";
            stringRows[8] = "列8";
            stringRows[9] = "列9";

            // int型の行を生成します。
            var intRows = new int[10];
            for (int i = 0; i < 10; i++)
            {
                intRows[i] = i;
            }

            // データグリッドに行を追加します。
            var rows = new List<object>();
            rows.Add(stringRows);
            rows.Add(intRows);
            dataGrid.ItemsSource = rows;
        }

        /**
         * @brief データグリッドにカラムを追加します。
         */
        void AddColumn(int index)
        {
            var column = new DataGridTextColumn();
            column.Header = $"項目{index}";
            column.Binding = new Binding("[" + index + "]");
            dataGrid.Columns.Add(column);
        }
    }
}
DataGridSpannedCellPanel.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace WPFGridColumnSpan
{
    class DataGridSpannedCellPanel : DataGridCellsPanel
    {
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            if (DataContext is IEnumerable)
            {
                // 親クラスのメソッドを呼び出します。
                base.ArrangeOverride(arrangeSize);

                var data = ((IEnumerable)DataContext).Cast<Object>();
                double totalPreviousWidth = 0;
                double totalPos = 0;

                var columnSize = new List<int>();
                for (int i = 0; i < data.Count(); ++i)
                {
                    var element = data.ElementAt(i);
                    Object nextElement = null;

                    var uiElement = InternalChildren[i];
                    if (data.Count() > i + 1)
                    {
                        nextElement = data.ElementAt(i + 1);
                    }

                    if (Object.ReferenceEquals(element, nextElement) && element != null)
                    {
                        totalPreviousWidth += uiElement.RenderSize.Width;
                        uiElement.Arrange(new Rect(new Point(0, 0), new Size(0, 0)));
                    }
                    else
                    {
                        if (totalPreviousWidth > 0)
                        {
                            uiElement.Arrange(
                                new Rect(
                                    new Point(totalPos, 0),
                                    new Size(totalPreviousWidth + uiElement.RenderSize.Width, uiElement.RenderSize.Height))
                            );
                        }
                        totalPos += uiElement.RenderSize.Width;
                        totalPreviousWidth = 0;
                    }
                }
                return arrangeSize;
            }
            else
            {
                return base.ArrangeOverride(arrangeSize);
            }
        }
    }
}

目次へ

3. おわりに

ずっとDataGridの列方向のセル結合の方法を探していました。
ようやく見つかりましたが、思ったより簡単にできないようです。
まだ列方向のセル結合の原理は理解していないので、原理を理解したいと思います。

GEEK JOB

実戦で役立つ C#プログラミングのイディオム/定石&パターン

実戦で役立つ C#プログラミングのイディオム/定石&パターン

紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。

目次へ


私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。

また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。

EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688

目次へ