FC2ブログ

C#等と戯れる日々

C#やその他諸々と戯れる日々。

マルチヘッダDataGridメモ-参(コントロールテンプレート)

まずはマルチヘッダ用のコントロールが必要となる。
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.Windows.Threading;

namespace TawamureDays {

    /// <summary>
    /// DataGrid マルチカラムヘッダ用コントロール
    /// </summary>
    [ContentProperty("Content")]
    public class DataGridMultiHeader : ContentControl {

        #region コンストラクタ

        /// <summary>
        /// staticコンストラクタ
        /// </summary>
        static DataGridMultiHeader() {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridMultiHeader),
                            new FrameworkPropertyMetadata(typeof(DataGridMultiHeader)));
        }

        #endregion
    }
}

ContentPropertyは、ContentControlのお約束な属性クラス。
マルチヘッダDataGridメモ-弐(DataGridの構造を理解する)で挙げたプロパティと連携する為の依存関係プロパティを実装する。
        /// <summary>
        /// セル用パネルの水平方向オフセット値を取得|設定します。
        /// </summary>
        private double CellsPanelHorizontalOffset {
            get { return (double)GetValue(CellsPanelHorizontalOffsetProperty); }
            set { SetValue(CellsPanelHorizontalOffsetProperty, value); }
        }

        /// <summary>セル用パネルの水平方向オフセット値</summary>
        private static readonly DependencyProperty CellsPanelHorizontalOffsetProperty =
            DependencyProperty.Register("CellsPanelHorizontalOffset", typeof(double),
                                    typeof(DataGridMultiHeader), new UIPropertyMetadata(0D));

        /// <summary>
        /// 非固定列ViewPort(表示スペース)の水平方向オフセット値を取得|設定します。
        /// </summary>
        private double NonFrozenColumnsViewportHorizontalOffset {
            get { return (double)GetValue(NonFrozenColumnsViewportHorizontalOffsetProperty); }
            set { SetValue(NonFrozenColumnsViewportHorizontalOffsetProperty, value); }
        }

        /// <summary>非固定列ViewPort(表示スペース)の水平方向オフセット値</summary>
        private static readonly DependencyProperty NonFrozenColumnsViewportHorizontalOffsetProperty =
            DependencyProperty.Register("NonFrozenColumnsViewportHorizontalOffset", typeof(double),
                                    typeof(DataGridMultiHeader), new UIPropertyMetadata(0D));

        /// <summary>
        /// 垂直方向のスクロールバーの可視状態を取得|設定します。
        /// </summary>
        private Visibility VerticalScrollBarVisibility {
            get { return (Visibility)GetValue(VerticalScrollBarVisibilityProperty); }
            set { SetValue(VerticalScrollBarVisibilityProperty, value); }
        }

        /// <summary>垂直方向のスクロールバーの可視状態</summary>
        private static readonly DependencyProperty VerticalScrollBarVisibilityProperty =
            DependencyProperty.Register("VerticalScrollBarVisibility", typeof(Visibility),
                                    typeof(DataGridMultiHeader), new UIPropertyMetadata(Visibility.Visible));

        /// <summary>
        /// 垂直方向のスクロールバーの幅を取得|設定します。
        /// </summary>
        private double VerticalScrollBarWidth {
            get { return (double)GetValue(VerticalScrollBarWidthProperty); }
            set { SetValue(VerticalScrollBarWidthProperty, value); }
        }

        /// <summary>垂直方向のスクロールバーの幅</summary>
        private static readonly DependencyProperty VerticalScrollBarWidthProperty =
            DependencyProperty.Register("VerticalScrollBarWidth", typeof(double),
                                    typeof(DataGridMultiHeader), new UIPropertyMetadata(0D));

次、テンプレートを作るにあたって、基本的な構造を考える。
DataGridが持つ列ヘッダは、専用のItemsControlに格納されている。更にこのItemsControlには、専用のパネルクラスが利用されている。しかも、DataGridというコントロールの内部で利用される事が前提となっている、いわゆるワンオフなクラス群だったりする。最初、これ(DataGrid内で使われているロジック)を再利用できないかと、ソースコードとにらめっこした。大体は理解できるんだけど、マルチヘッダに利用できるか?と考えたら、「無理っぽい」という結論になってしまった。なので、WPF multi-column super headerにあったように、Gridパネルを駆使してどうにかする方法を考えた次第。

コントロールテンプレート実装メモ:
①DataGridを覆う為のDockPanelを準備する。
②DataGridの上部に張り付く為のBorder(DockPanel.Dock=Top)を①のDockPanelに追加する。
③DataGridはContentに設定される前提なので、ContentPresenterを①のDockPanelに追加する。
なので最も外側だけで見ると、DockPanel{Border(Top), ContentPresenter}になる。
④Border内に、各々の領域を確保する為のGridを追加する。
⑤④で追加したGridに、以下のコントロールを追加する。
 Rectangle:CellsPanelHorizontalOffset分の広さを確保する為のプレースホルダ
      DataGridRowHeaderの上あたりに居座る。
 Grid:固定列分の領域を確保するためのプレースホルダ。固定列用のマルチヘッダを表示させる領域になる。
 ScrollViewer:可変列分の領域を確保する為のプレースホルダ。DataGridがスクロールされのと同じようにスクロールされる必要がある。
 Rectangle:垂直方向のスクロールバー分の領域を確保する為のプレースホルダ。スクロールバーがAutoだった時も考える。
※各プレースホルダの幅や表示状態は、領域確保の対象とする部分と連携される。
マルチヘッダの部分は、GridとScrollViewer内に収められる。

(追記)
③くらいまでの段階におけるControlTemplate。
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TawamureDays">
    <Style TargetType="{x:Type local:DataGridMultiHeader}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:DataGridMultiHeader}">
                    <DockPanel>
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                SnapsToDevicePixels="True"
                                DockPanel.Dock="Top">
                        </Border>
                        <ContentPresenter/>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Styleの宣言、TargetTypeの設定、TemplateプロパティへのSetはお約束。カスタムコントロールのControlTemplateもワンオフ品かな。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2012/11/27(火) 23:16:00|
  2. WPF4
  3. | トラックバック:0
  4. | コメント:0
<<Template内のコントロールを検索する。 | ホーム | マルチヘッダDataGridメモ-弐(DataGridの構造を理解する)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://tawamuredays.blog.fc2.com/tb.php/154-acfef106
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

チャプターマン

Author:チャプターマン
FC2ブログへようこそ!

最新記事

最新コメント

最新トラックバック

月別アーカイブ

カテゴリ

未分類 (4)
WPF4 (192)
C# (71)
サーバ (1)
C# 5.0 (1)
WPF4.5 (2)
WEB (6)
WCF (2)
物欲 (2)
Windows (3)
Windows.Forms (0)
仕事 (2)
.NET5 (4)
.NET MAUI (2)
Blazor (1)

カウンター

FC2無料カウンターFC2無料カウンターFC2無料カウンターFC2無料カウンターFC2無料カウンターFC2無料カウンターFC2無料カウンターFC2無料カウンター

検索フォーム

RSSリンクの表示

リンク

このブログをリンクに追加する

ブロとも申請フォーム

この人とブロともになる

QRコード

QR