using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Collections.ObjectModel;
using System.Windows;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Data;
namespace EnumBindings
{
public class TableGridCell : Border
{
public TableGridCell()
{
}
public TableGridCell(UIElement content)
{
this.Child = content;
}
}
[ContentProperty("Children")]
public class TableGridRow : RowDefinition
{
private TableRowElementCollection m_children;
class TableRowElementCollection : Collection<UIElement>
{
public TableRowElementCollection (TableGridRow row)
{
TableRow = row;
}
public TableGridRow TableRow { get; private set; }
protected override void ClearItems()
{
for (int i = Count-1; i >= 0; i--)
{
TableRow.OnRemoveChild(i, this[i]);
}
base.ClearItems();
}
protected override void InsertItem(int colIndex, UIElement child)
{
TableRow.OnAddElement(colIndex, child);
base.InsertItem(colIndex, child);
}
protected override void RemoveItem(int index)
{
TableRow.OnRemoveChild(index, this[index]);
base.RemoveItem(index);
}
protected override void SetItem(int index, UIElement item)
{
int oldCount = TableRow.Table.Children.Count;
TableRow.OnRemoveChild(index, this[index]);
TableRow.OnAddElement(index, item);
base.SetItem(index, item);
}
}
private List<TableGridCell> m_cells;
public TableGridRow()
{
m_cells = new List<TableGridCell>();
m_children = new TableRowElementCollection(this);
}
private void OnRemoveChild(int colIndex, UIElement child)
{
TableGridCell cell = m_cells[colIndex];
m_cells.RemoveAt(colIndex);
if (Table != null)
{
Table.Children.Remove(cell);
}
for (int i = colIndex; i < m_cells.Count; i++)
{
cell = m_cells[i];
cell.SetValue(Grid.ColumnProperty, i);
}
}
private int GetStartingGridColumFor(int colIndex)
{
if (colIndex == 0) return 0;
TableGridCell previousCell = m_cells[colIndex-1];
return (int)previousCell.GetValue(Grid.ColumnProperty) + (int)previousCell.GetValue(Grid.ColumnSpanProperty);
}
private void OnAddElement(int colIndex, UIElement child)
{
TableGridCell cell = child as TableGridCell;
if (cell == null)
{
cell = new TableGridCell(child);
}
m_cells.Insert(colIndex, cell);
int gridColIndex = GetStartingGridColumFor(colIndex);
cell.SetValue(Grid.ColumnProperty, gridColIndex);
for (int i = colIndex + 1; i < m_cells.Count; i++)
{
cell = m_cells[i];
cell.SetValue(Grid.ColumnProperty, GetStartingGridColumFor(i));
}
if (Table != null)
{
cell.SetValue(Grid.RowProperty, RowIndex);
BindingOperations.SetBinding(cell, FrameworkElement.StyleProperty, new Binding() { Source = Table, Path = new PropertyPath("CellStyle") });
AdjustNumberOfTableColumns();
//Table.Children.Add(cell);
Table.AddInternalChild(cell);
}
}
private void AdjustNumberOfTableColumns()
{
int lastGridColIndex = GetStartingGridColumFor(m_cells.Count);
while (Table.ColumnDefinitions.Count < lastGridColIndex)
{
Table.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Auto) });
}
}
public IList Children { get { return m_children; } }
private TableGrid m_table;
public TableGrid Table
{
get { return m_table; }
set {
if (value != null)
{
m_table = value;
int colIndex = 0;
foreach (TableGridCell cell in m_cells)
{
BindingOperations.SetBinding(cell, FrameworkElement.StyleProperty, new Binding() { Source = Table, Path = new PropertyPath("CellStyle") });
AdjustNumberOfTableColumns();
//Table.Children.Add(cell);
Table.RemoveInternalChild(cell);
colIndex++;
}
}
else
{
foreach (TableGridCell cell in m_cells)
{
BindingOperations.ClearBinding(cell, FrameworkElement.StyleProperty);
// Table.Children.Remove(cell);
Table.RemoveInternalChild(cell);
}
m_table = value;
}
}
}
private int m_rowIndex;
public int RowIndex {
get { return m_rowIndex; }
set
{
m_rowIndex = value;
foreach (TableGridCell cell in m_cells)
{
cell.SetValue(Grid.RowProperty, m_rowIndex);
}
}
}
}
[ContentProperty("Children")]
public class TableRow : FrameworkElement
{
private TableRowElementCollection m_children;
class TableRowElementCollection : Collection<UIElement>
{
public TableRowElementCollection (TableRow row)
{
TableRow = row;
}
public TableRow TableRow { get; private set; }
protected override void ClearItems()
{
for (int i = Count-1; i >= 0; i--)
{
TableRow.OnRemoveChild(i, this[i]);
}
base.ClearItems();
}
protected override void InsertItem(int colIndex, UIElement child)
{
TableRow.OnAddElement(colIndex, child);
base.InsertItem(colIndex, child);
}
protected override void RemoveItem(int index)
{
TableRow.OnRemoveChild(index, this[index]);
base.RemoveItem(index);
}
protected override void SetItem(int index, UIElement item)
{
int oldCount = TableRow.Table.Children.Count;
TableRow.OnRemoveChild(index, this[index]);
TableRow.OnAddElement(index, item);
base.SetItem(index, item);
}
}
private List<TableGridCell> m_cells;
public TableRow()
{
m_cells = new List<TableGridCell>();
m_children = new TableRowElementCollection(this);
}
private void OnRemoveChild(int colIndex, UIElement child)
{
TableGridCell cell = m_cells[colIndex];
m_cells.RemoveAt(colIndex);
RemoveLogicalChild(cell);
if (Table != null)
{
Table.Children.Remove(cell);
}
for (int i = colIndex; i < m_cells.Count; i++)
{
cell = m_cells[i];
cell.SetValue(Grid.ColumnProperty, i);
}
}
private int GetStartingGridColumFor(int colIndex)
{
if (colIndex == 0) return 0;
TableGridCell previousCell = m_cells[colIndex-1];
return (int)previousCell.GetValue(Grid.ColumnProperty) + (int)previousCell.GetValue(Grid.ColumnSpanProperty);
}
private void OnAddElement(int colIndex, UIElement child)
{
TableGridCell cell = child as TableGridCell;
if (cell == null)
{
cell = new TableGridCell(child);
}
m_cells.Insert(colIndex, cell);
int gridColIndex = GetStartingGridColumFor(colIndex);
cell.SetValue(Grid.ColumnProperty, gridColIndex);
for (int i = colIndex + 1; i < m_cells.Count; i++)
{
cell = m_cells[i];
cell.SetValue(Grid.ColumnProperty, GetStartingGridColumFor(i));
}
if (Table != null)
{
cell.SetValue(Grid.RowProperty, RowIndex);
BindingOperations.SetBinding(cell, FrameworkElement.StyleProperty, new Binding() { Source = Table, Path = new PropertyPath("CellStyle") });
AdjustNumberOfTableColumns();
//Table.Children.Add(cell);
Table.AddInternalChild(cell);
}
AddLogicalChild(cell);
}
private void AdjustNumberOfTableColumns()
{
int lastGridColIndex = GetStartingGridColumFor(m_cells.Count);
while (Table.ColumnDefinitions.Count < lastGridColIndex)
{
Table.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Auto) });
}
}
public IList Children { get { return m_children; } }
private TableGrid m_table;
public TableGrid Table
{
get { return m_table; }
set {
if (value != null)
{
m_table = value;
int colIndex = 0;
foreach (TableGridCell cell in m_cells)
{
BindingOperations.SetBinding(cell, FrameworkElement.StyleProperty, new Binding() { Source = Table, Path = new PropertyPath("CellStyle") });
AdjustNumberOfTableColumns();
//Table.Children.Add(cell);
RemoveLogicalChild(cell);
Table.AddInternalChild(cell);
AddLogicalChild(cell);
colIndex++;
}
}
else
{
foreach (TableGridCell cell in m_cells)
{
BindingOperations.ClearBinding(cell, FrameworkElement.StyleProperty);
// Table.Children.Remove(cell);
Table.RemoveInternalChild(cell);
}
m_table = value;
}
}
}
private int m_rowIndex;
public int RowIndex {
get { return m_rowIndex; }
set
{
m_rowIndex = value;
foreach (TableGridCell cell in m_cells)
{
cell.SetValue(Grid.RowProperty, m_rowIndex);
}
}
}
public int ColumnWidth
{
get
{
return GetStartingGridColumFor(m_cells.Count);
}
}
}
[ContentProperty("TableRows")]
[StyleTypedProperty(Property="CellStyle", StyleTargetType=typeof(TableGridCell))]
public class TableGrid : Grid
{
private class TableRowsCollection : Collection<TableRow>
{
public TableRowsCollection(TableGrid table)
{
Table = table;
}
public TableGrid Table { get; private set; }
protected override void InsertItem(int index, TableRow item)
{
Table.InsertTableRow(index, item);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
Table.RemoveTableRow(index);
base.RemoveItem(index);
}
protected override void SetItem(int index, TableRow item)
{
Table.RemoveTableRow(index);
Table.InsertTableRow(index, item);
base.SetItem(index, item);
}
protected override void ClearItems()
{
for (int i = Count-1; i >= 0; i--)
{
Table.RemoveTableRow(i);
}
base.ClearItems();
}
}
public TableGrid()
{
m_tableRows = new TableRowsCollection(this);
HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
VerticalAlignment = System.Windows.VerticalAlignment.Top;
}
public Style CellStyle
{
get { return (Style)GetValue(CellStyleProperty); }
set { SetValue(CellStyleProperty, value); }
}
// Using a DependencyProperty as t he backing store for CellStyle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellStyleProperty =
DependencyProperty.Register("CellStyle", typeof(Style), typeof(TableGrid), new UIPropertyMetadata(null));
private TableRowsCollection m_tableRows;
public IList TableRows
{
get { return m_tableRows; }
}
private void RemoveTableRow(int rowIndex)
{
TableRow row = m_tableRows[rowIndex];
row.Table = null;
RemoveLogicalChild(row);
InternalChildren.Remove(row);
// Adjust row index for all items below.
for (int i = rowIndex; i < m_tableRows.Count; i++)
{
m_tableRows[i].RowIndex = i;
}
}
internal void AddInternalChild(UIElement child)
{
InternalChildren.Add(child);
RemoveLogicalChild(child);
}
internal void RemoveInternalChild(UIElement child)
{
InternalChildren.Remove(child);
}
private void InsertTableRow(int rowIndex, Object element)
{
if (element == null) throw new ArgumentNullException();
TableRow row = element as TableRow;
if (row == null)
{
UIElement uielement = element as UIElement;
if (uielement == null) throw new ArgumentException("Element added to TableGrid must be a TableGridRow or a UIElement");
row = new TableRow();
row.Children.Add(uielement);
}
InternalChildren.Add(row);
row.Table = this;
row.RowIndex = rowIndex;
// Adjust row index for all items below.
for (int i = rowIndex+1; i < m_tableRows.Count; i++)
{
m_tableRows[i].RowIndex = i;
}
// Ensure that number of rowdefinitions are sufficient
while (RowDefinitions.Count < m_tableRows.Count)
{
RowDefinitions.Add(new RowDefinition());
}
}
}
}