Menu


Microsoft Most Valuable Person

グリッドにデータバインドする

GridControllApp
グリッドの表示 (要 Silverlightプラグイン バージョン2.0以降)

ソースコード

GridControlApp.zip (15.1KB)

アプリケーションの説明

従業員情報のリストをデータバインドし、グリッドレイアウト上に並べて表示する。

ソースコードの説明

画面のXAMLを抜粋する。GridControl.ItemTemplateに注意。

<my:GridControl x:Name="gc">
  <my:GridControl.Template>
    <ControlTemplate>
      <Border
        CornerRadius="10"
        BorderBrush="Black"
        BorderThickness="2"
        Background="AliceBlue">
        <ItemsPresenter Margin="5" />
      </Border>
    </ControlTemplate>
  </my:GridControl.Template>
  <my:GridControl.ItemTemplate>
    <DataTemplate>
      <Canvas>
        <Button Content="{Binding EmpNo}" />
        <Button Content="{Binding EName}" />
        <Button Content="{Binding Job}" />
        <Button Content="{Binding Sal}" />
      </Canvas>
    </DataTemplate>
  </my:GridControl.ItemTemplate>
</my:GridControl>

GridControl.ItemTemplateにCanvasが設定され、その中にButtonが4つ並んでいる。

描画の際、Canvasに含まれている内容をGridに移す。Canvasはコンテナとしてしか使っていないためCanvasである必然性はない。(Panelを継承さえしていればいい。)

GridControlのソースコードは以下。

using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace GridControlApp
{
  public class GridControl : ItemsControl
  {
    public GridControl()
    {
      this.DefaultStyleKey = typeof(GridControl);
    }

    protected override Size MeasureOverride(Size availableSize)
    {
      base.MeasureOverride(availableSize);
      var all = SelfAndDescendants(this);
      foreach (DependencyObject d in all)
      {
        ((UIElement)d).InvalidateMeasure();
      }
      Grid itemsPanel = all
        .Where(x => x is Grid)
        .FirstOrDefault() as Grid;
      int rowsCount = itemsPanel.Children.Count;
      List<Panel> contentPanels = itemsPanel.Children
        .Select(presenter => VisualTreeHelper.GetChild(presenter, 0))
        .Select(panel => (Panel)panel)
        .ToList();
      int columnsCount = 0;
      foreach(Panel p in contentPanels)
      {
        if (columnsCount < p.Children.Count)
        {
          columnsCount = p.Children.Count;
        }
      }
      itemsPanel.Children.Clear();
      for (int i = 0; i < rowsCount; i++)
      {
        RowDefinition r = new RowDefinition { Height = GridLength.Auto };
        itemsPanel.RowDefinitions.Add(r);
      }
      for (int i = 0; i < columnsCount; i++)
      {
        ColumnDefinition c = new ColumnDefinition { Width = GridLength.Auto };
        itemsPanel.ColumnDefinitions.Add(c);
      }
      for (int y = 0; y < rowsCount; y++)
      {
        for (int x = 0; contentPanels[y].Children.Count > 0; x++)
        {
          Panel p = contentPanels[y];
          FrameworkElement element = p.Children[0] as FrameworkElement;
          p.Children.RemoveAt(0);
          element.SetValue(Grid.ColumnProperty, x);
          element.SetValue(Grid.RowProperty, y);
          element.DataContext = p.DataContext;
          itemsPanel.Children.Add(element);
        }
      }
      return base.MeasureOverride(availableSize);
    }

    private static IEnumerable<DependencyObject>
      SelfAndDescendants(DependencyObject d)
    {
      if (d == null) yield break;
      yield return d;
      int count = VisualTreeHelper.GetChildrenCount(d);
      for (int i = 0; i < count; i++)
      {
        DependencyObject child = VisualTreeHelper.GetChild(d, i);
        foreach (DependencyObject subitem in SelfAndDescendants(child))
        {
          yield return subitem;
        }
      }
    }
  }
}

Silverlight インデックスへ戻る


Last Update: 2012-12-30 18:37:48