#region License Information
/* HeuristicLab
* Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using HeuristicLab.DataImporter.Data.Command;
using HeuristicLab.DataImporter.Data.Model;
namespace HeuristicLab.DataImporter.Data.View {
public delegate void ColumnGroupActivatedEventHandler(object sender, bool addToActiveColumnGroups);
public partial class ColumnGroupView : UserControl {
private TextBox txtColumnName;
private ColumnGroupView()
: base() {
InitializeComponent();
txtColumnName = new TextBox();
this.splitContainer1.Panel2.Controls.Add(txtColumnName);
txtColumnName.Visible = false;
txtColumnName.Leave += new EventHandler(txtColumnName_Leave);
txtColumnName.KeyDown += new KeyEventHandler(txtColumnName_KeyDown);
this.dataGridView.EnableHeadersVisualStyles = false;
this.dataGridView.Dock = DockStyle.Top | DockStyle.Bottom;
this.dataGridView.VirtualMode = true;
this.dataGridView.ShowCellToolTips = false;
this.dataGridView.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(dataGridView_ColumnHeaderMouseClick);
this.dataGridView.ColumnHeaderMouseDoubleClick += new DataGridViewCellMouseEventHandler(dataGridView_ColumnHeaderMouseDoubleClick);
this.dataGridView.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGridView_ColumnWidthChanged);
this.dataGridView.MouseClick += new MouseEventHandler(dataGridView_MouseClick);
this.dataGridView.SelectionChanged += new EventHandler(dataGridView_SelectionChanged);
this.dataGridView.AllowUserToOrderColumnsChanged += new EventHandler(dataGridView_AllowUserToOrderColumnsChanged);
this.dataGridView.KeyDown += new KeyEventHandler(dataGridView_KeyDown);
this.dataGridView.RowHeadersWidthChanged += new EventHandler(dataGridView_RowHeadersWidthChanged);
this.dataGridView.CellMouseEnter += new DataGridViewCellEventHandler(dataGridView_CellMouseEnter);
//delegates for virtual mode
this.dataGridView.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView_CellValueNeeded);
this.dataGridView.CellValuePushed += new DataGridViewCellValueEventHandler(dataGridView_CellValuePushed);
this.dataGridView.UserDeletingRow += new DataGridViewRowCancelEventHandler(dataGridView_UserDeletingRow);
}
private ColumnGroupView(ColumnGroup columnGroup)
: this() {
this.ColumnGroup = columnGroup;
this.ColumnGroup.Changed += this.ColumnGroupChanged;
this.dataGridView.ClearSelection();
this.state = ColumnGroupState.None;
this.UpdateDataGridView();
}
public ColumnGroupView(ColumnGroup columnGroup, CommandChain commandChain)
: this(columnGroup) {
this.commandChain = commandChain;
}
public bool ColumnGroupActive {
get { return this.ColumnGroup.Active; }
set {
this.ColumnGroup.Active = value;
if (this.ColumnGroup.Active)
this.txtColumnGroupName.BackColor = Color.LightGreen;
else {
this.dataGridView.ClearSelection();
this.txtColumnGroupName.BackColor = Control.DefaultBackColor;
}
UpdateStateInformation();
}
}
private ColumnGroup columnGroup;
public ColumnGroup ColumnGroup {
get { return (ColumnGroup)this.columnGroup; }
private set { this.columnGroup = value; }
}
private Data.Model.DataSet DataSet {
get { return ((DataSetView)this.Parent).DataSet; }
}
private CommandChain commandChain;
public CommandChain CommandChain {
get { return this.commandChain; }
set { this.commandChain = value; }
}
public bool AllowReorderColumns {
get { return this.dataGridView.AllowUserToOrderColumns; }
set { this.dataGridView.AllowUserToOrderColumns = value; }
}
public int[] DisplayIndexes {
get {
int[] ret = new int[this.ColumnGroup.Columns.Count()];
for (int i = 0; i < this.dataGridView.Columns.Count; i++) {
ret[dataGridView.Columns[i].DisplayIndex] = i;
}
return ret;
}
}
public int MaxWidth {
get { return this.MaximumSize.Width; }
set {
this.MaximumSize = new Size(value, this.MaximumSize.Height);
this.dataGridView.MaximumSize = new Size(value, this.MaximumSize.Height);
RecalculateWidthOfControl();
}
}
//IMPORTANT: use the defined property to change the state, because the event StateChanged must be fired!
private ColumnGroupState state;
public ColumnGroupState State {
get { return this.state; }
protected set {
this.state = value;
FireStateChanged();
}
}
public event EventHandler StateChanged;
protected void FireStateChanged() {
OnStateChanged();
}
protected virtual void OnStateChanged() {
if (StateChanged != null) {
StateChanged(this, new EventArgs());
}
}
public event ColumnGroupActivatedEventHandler Activated;
public void FireActivated(bool addToActiveColumnGroups) {
OnActivated(addToActiveColumnGroups);
}
protected virtual void OnActivated(bool addToActiveColumnGroups) {
if (Activated != null) {
Activated(this, addToActiveColumnGroups);
}
}
private void UpdateStateInformation() {
this.UpdateStateInformation(false);
}
private void UpdateStateInformation(bool selectionChanged) {
ColumnGroupState newState = this.ColumnGroupActive ? ColumnGroupState.Active : ColumnGroupState.None;
foreach (ColumnBase col in ColumnGroup.SelectedColumns) {
if (col is DoubleColumn)
newState |= ColumnGroupState.DoubleColumnSelected;
else if (col is StringColumn)
newState |= ColumnGroupState.StringColumnSelected;
else if (col is DateTimeColumn)
newState |= ColumnGroupState.DateTimeColumnSelected;
else if (col is ProgrammableColumn)
newState |= ColumnGroupState.ProgrammableColumnSelected;
if (col.ContainsNullValues)
newState |= ColumnGroupState.AnySelectedColumnContainsNull;
}
if (ColumnGroup.Sorted) {
if (ColumnGroup.SelectedColumns.Any(col => col.SortOrder == SortOrder.None))
newState |= ColumnGroupState.AnySelectedColumnNotSorted;
else
newState |= ColumnGroupState.Sorted;
}
if (newState != this.State || selectionChanged)
this.State = newState;
}
private void PasteClipboardContent() {
if (dataGridView.CurrentCell != null) {
string values = Clipboard.GetText();
values = values.Remove(values.Length - Environment.NewLine.Length);
this.commandChain.Add(new PasteValuesCommand(DataSet, this.ColumnGroup.Name, dataGridView.CurrentCell.ColumnIndex,
dataGridView.CurrentCell.RowIndex, values));
}
}
private void CopyClipboardContent() {
if (dataGridView.SelectedCells.Count != 0) {
StringBuilder s = new StringBuilder();
DataGridViewCell cell;
int minRowIndex = dataGridView.SelectedCells[0].RowIndex;
int maxRowIndex = dataGridView.SelectedCells[dataGridView.SelectedCells.Count - 1].RowIndex;
int minColIndex = dataGridView.SelectedCells[0].ColumnIndex;
int maxColIndex = dataGridView.SelectedCells[dataGridView.SelectedCells.Count - 1].ColumnIndex;
if (minRowIndex > maxRowIndex) {
int temp = minRowIndex;
minRowIndex = maxRowIndex;
maxRowIndex = temp;
}
if (minColIndex > maxColIndex) {
int temp = minColIndex;
minColIndex = maxColIndex;
maxColIndex = temp;
}
if (maxRowIndex == dataGridView.RowCount - 1)
maxRowIndex--;
for (int i = minRowIndex; i < maxRowIndex + 1; i++) {
for (int j = minColIndex; j < maxColIndex + 1; j++) {
cell = dataGridView[j, i];
if (cell.Selected) {
if (cell.Value != null)
s.Append(cell.Value.ToString());
}
if (j != maxColIndex)
s.Append("\t");
}
s.Append(Environment.NewLine);
}
Clipboard.SetText(s.ToString());
}
}
public override void Refresh() {
base.Refresh();
if (ColumnGroup != null) {
this.UpdateDataGridView();
} else {
dataGridView.ColumnCount = 0;
dataGridView.RowCount = 0;
}
}
public void ColumnGroupChanged(object sender, EventArgs e) {
this.UpdateDataGridView();
}
private void UpdateDataGridView() {
int firstVisibleRowIndex = 0;
int firstVisibleColIndex = 0;
if (dataGridView.FirstDisplayedCell != null) {
if (firstVisibleColIndex < ColumnGroup.Columns.Count())
firstVisibleColIndex = dataGridView.FirstDisplayedCell.ColumnIndex;
if (firstVisibleRowIndex < ColumnGroup.RowCount)
firstVisibleRowIndex = dataGridView.FirstDisplayedCell.RowIndex;
}
//needed because otherwise columns could not be added
this.dataGridView.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
if (dataGridView.ColumnCount != ColumnGroup.Columns.Count()) {
this.dataGridView.ColumnCount = ColumnGroup.Columns.Count();
for (int i = 0; i < ColumnGroup.Columns.Count(); i++) {
dataGridView.Columns[i].SortMode = DataGridViewColumnSortMode.Programmatic;
}
}
for (int i = 0; i < ColumnGroup.Columns.Count(); i++)
dataGridView.Columns[i].HeaderText = ColumnGroup.Columns.ElementAt(i).ToString().Insert(ColumnGroup.Columns.ElementAt(i).ToString().IndexOf('<'), "\n");
// needed for performance reasons; further information at http://whiletrue.nl/blog/?p=38
if (dataGridView.RowCount != ColumnGroup.RowCount + (ColumnGroup.Columns.Count() == 0 ? 0 : 1)) {
//event handler must be deregistered cause otherwise cellvaluepushed is fired again
this.dataGridView.CellValuePushed -= new DataGridViewCellValueEventHandler(dataGridView_CellValuePushed);
if (Math.Abs(dataGridView.RowCount - ColumnGroup.RowCount) > 10)
dataGridView.Rows.Clear();
bool rowAdded = dataGridView.RowCount == ColumnGroup.RowCount && dataGridView.RowCount != 0;
dataGridView.RowCount = ColumnGroup.RowCount + (!ColumnGroup.Columns.Any() ? 0 : 1);
if (rowAdded) {
Point p = this.dataGridView.CurrentCellAddress;
p.Y += 1;
this.dataGridView.CurrentCell = this.dataGridView.Rows[p.Y].Cells[p.X];
this.dataGridView.ClearSelection();
this.dataGridView.CurrentCell.Selected = true;
}
this.dataGridView.CellValuePushed += new DataGridViewCellValueEventHandler(dataGridView_CellValuePushed);
}
UpdateDataGridViewHeaderCells();
this.dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
this.dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders);
if (dataGridView.RowCount != 0 && dataGridView.ColumnCount != 0) {
if (firstVisibleColIndex >= dataGridView.ColumnCount)
firstVisibleColIndex = 0;
if (firstVisibleRowIndex >= dataGridView.RowCount)
firstVisibleRowIndex = 0;
dataGridView.FirstDisplayedCell = dataGridView[firstVisibleColIndex, firstVisibleRowIndex];
}
UpdateSortGlyph();
this.txtColumnGroupName.Text = this.ColumnGroup.Name + " " + ColumnGroup.RowCount + " rows";
RecalculateWidthOfControl();
this.dataGridView.Invalidate();
UpdateStateInformation();
}
private void UpdateDataGridViewHeaderCells() {
for (int i = 1; i <= columnGroup.RowCount; i++)
dataGridView.Rows[i].HeaderCell.Value = i.ToString();
}
private void dataGridView_ColumnHeaderMouseClick(object sender, System.Windows.Forms.DataGridViewCellMouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
this.commandChain.Add(new SortCommand(DataSet, this.ColumnGroup.Name,
e.ColumnIndex, (Control.ModifierKeys & Keys.Control) == Keys.Control));
//this.UpdateSortGlyph();
//this.dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
//UpdateStateInformation();
}
}
private void dataGridView_ColumnHeaderMouseDoubleClick(object sender, System.Windows.Forms.DataGridViewCellMouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
dataGridView.ClearSelection();
Rectangle rect = dataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
ColumnBase col = this.ColumnGroup.Columns.ElementAt(e.ColumnIndex);
txtColumnName.Text = col.Name;
txtColumnName.Size = rect.Size;
txtColumnName.Location = rect.Location;
txtColumnName.Visible = true;
txtColumnName.Focus();
txtColumnName.BringToFront();
}
}
private void UpdateSortGlyph() {
System.Collections.IEnumerator e = this.dataGridView.Columns.GetEnumerator();
e.MoveNext();
foreach (SortOrder sortOrder in this.ColumnGroup.SortOrdersForColumns) {
((DataGridViewColumn)e.Current).HeaderCell.SortGlyphDirection = sortOrder;
e.MoveNext();
}
}
private void dataGridView_SelectionChanged(object sender, EventArgs e) {
int nullValuesCount = 0;
int totalValuesCount = 0;
IComparable minimum = "";
IComparable maximum = "";
double? mean = null;
double? median = null;
double? stddev = null;
ColumnBase column;
this.ColumnGroup.ClearSelectedColumns();
if (this.dataGridView.SelectedColumns.Count != 0) {
foreach (DataGridViewColumn col in this.dataGridView.SelectedColumns) {
column = this.ColumnGroup.Columns.ElementAt(col.Index);
column.Selected = true;
nullValuesCount += column.NullValuesCount;
totalValuesCount += column.NonNullValuesCount;
}
if (this.dataGridView.SelectedColumns.Count == 1) {
column = this.ColumnGroup.Columns.ElementAt(dataGridView.SelectedColumns[0].Index);
minimum = column.Minimum;
maximum = column.Maximum;
if (column is DoubleColumn) {
mean = ((DoubleColumn)column).Mean;
stddev = ((DoubleColumn)column).StandardDeviation;
median = ((DoubleColumn)column).Median;
}
}
}
lblNullValues.Text = nullValuesCount.ToString();
lblValues.Text = totalValuesCount.ToString();
lblMinimum.Text = minimum == null ? "" : minimum.ToString();
lblMaximum.Text = maximum == null ? "" : maximum.ToString();
lblMean.Text = mean == null ? "" : mean.ToString();
lblStdDev.Text = stddev == null ? "" : stddev.ToString();
lblMedian.Text = median == null ? "" : median.ToString();
UpdateStateInformation(true);
}
private void dataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) {
RecalculateWidthOfControl();
}
private void RecalculateWidthOfControl() {
int width = 0;
foreach (DataGridViewColumn col in this.dataGridView.Columns)
width += col.Width;
//no columns in datagrid
if (width != 0) {
width += this.dataGridView.RowHeadersWidth;
//datagridview.controls[1] is always the vertical scrollbar
if (dataGridView.Controls[1].Visible)
width += 20;
}
this.dataGridView.Width = width;
this.Width = width;
}
private void dataGridView_MouseClick(object sender, MouseEventArgs e) {
this.ColumnGroupActive = true;
this.FireActivated(false);
if (this.dataGridView.AllowUserToOrderColumns || e.Clicks >= 2)
return;
System.Windows.Forms.DataGridView.HitTestInfo hit = dataGridView.HitTest(e.X, e.Y);
// row header click
if (hit.ColumnIndex == -1 && hit.RowIndex >= 0) {
if (e.Button == MouseButtons.Right) {
this.commandChain.Add(new InsertRowCommand(DataSet, this.ColumnGroup.Name, hit.RowIndex));
} else {
if (dataGridView.SelectionMode != DataGridViewSelectionMode.RowHeaderSelect)
dataGridView.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
}
} // column header click
else if (hit.RowIndex == -1 && hit.ColumnIndex >= 0 && e.Button == MouseButtons.Left) {
if (dataGridView.SelectionMode != DataGridViewSelectionMode.ColumnHeaderSelect)
dataGridView.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect;
}
}
private void dataGridView_AllowUserToOrderColumnsChanged(object sender, EventArgs e) {
if (this.dataGridView.AllowUserToOrderColumns)
this.dataGridView.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
}
private void dataGridView_KeyDown(object sender, KeyEventArgs e) {
//handle deletion of columns and emptying of cells
if (e.KeyCode == Keys.Delete) {
if (this.dataGridView.SelectedColumns.Count != 0)
this.commandChain.Add(new DeleteColumnCommand(DataSet, this.ColumnGroup.Name, ColumnGroup.SelectedColumnIndexes));
else if (this.dataGridView.SelectedRows.Count != 0) {
//to ensure that cells are not emptied before the rows got deleted
//deleting of rows handled by user deleting rows
} else if (this.dataGridView.SelectedCells.Count != 0) {
List cells = new List();
foreach (DataGridViewCell cell in this.dataGridView.SelectedCells) {
if (cell.RowIndex < this.ColumnGroup.Columns.ElementAt(cell.ColumnIndex).TotalValuesCount && cell.Value != null)
cells.Add(new Point(cell.ColumnIndex, cell.RowIndex));
}
if (cells.Count != 0)
this.commandChain.Add(new ChangeValuesToNullCommand(DataSet, this.ColumnGroup.Name, cells));
}
}
//handle paste of values
else if (e.Control && e.KeyCode == Keys.V)
PasteClipboardContent();
else if (e.Control && e.KeyCode == Keys.C)
CopyClipboardContent();
}
private void dataGridView_RowHeadersWidthChanged(object sender, EventArgs e) {
this.RecalculateWidthOfControl();
}
private void dataGridView_CellMouseEnter(object sender, DataGridViewCellEventArgs e) {
if (e.RowIndex == -1 && e.ColumnIndex != -1) {
toolTip.SetToolTip(this.dataGridView, ToExcelColumnIndex(e.ColumnIndex));
} else {
toolTip.Hide(this.dataGridView);
}
}
private string ToExcelColumnIndex(int index) {
//if (symb.Length == 1) { // 'A' .. 'Z'
// return TryTranslateColumnIndexDigit(symb[0], out columnIndex);
//} else if (symb.Length == 2) { // 'AA' ... 'ZZ'
// bool ok;
// int d0, d1;
// ok = TryTranslateColumnIndexDigit(symb[0], out d1) & TryTranslateColumnIndexDigit(symb[1], out d0);
// columnIndex = (d1 + 1) * 26 + d0;
// return ok;
//} else {
// columnIndex = 0;
// return false;
//}
#region digits
var digits = new char[] {
'#',
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z'};
int b = digits.Length - 1;
#endregion
string excelIndex = string.Empty;
index = index + 1;
while (index > 0) {
int d = index / b;
int rem = index % b;
index = d;
excelIndex = digits[rem] + excelIndex;
}
return excelIndex;
}
#region DataGridView virtual mode event handler
private void dataGridView_CellValueNeeded(object sender, System.Windows.Forms.DataGridViewCellValueEventArgs e) {
e.Value = ColumnGroup.Columns.ElementAt(e.ColumnIndex).GetValue(e.RowIndex);
}
private void dataGridView_CellValuePushed(object sender, System.Windows.Forms.DataGridViewCellValueEventArgs e) {
IComparable value = null;
try {
if (e.Value == null)
value = null;
else if (this.ColumnGroup.Columns.ElementAt(e.ColumnIndex).DataType == typeof(double?))
value = double.Parse((string)e.Value);
else if (this.ColumnGroup.Columns.ElementAt(e.ColumnIndex).DataType == typeof(DateTime?))
value = DateTime.Parse((string)e.Value);
else
value = e.Value.ToString();
}
catch (FormatException) {
}
if (e.RowIndex == this.dataGridView.RowCount - 1) {
IComparable[] row = new IComparable[this.ColumnGroup.Columns.Count()];
row[e.ColumnIndex] = value;
this.commandChain.Add(new AddRowCommand(this.DataSet, this.ColumnGroup.Name, row));
} else {
this.commandChain.Add(new ChangeValueCommand(this.DataSet, this.ColumnGroup.Name, e.ColumnIndex, e.RowIndex, value));
}
}
private void dataGridView_UserDeletingRow(object sender, System.Windows.Forms.DataGridViewRowCancelEventArgs e) {
e.Cancel = true;
if (e.Row.Index < this.ColumnGroup.RowCount) {
List positions;
if (this.dataGridView.AreAllCellsSelected(true))
positions = Enumerable.Range(0, this.ColumnGroup.RowCount).ToList();
else {
positions = new List();
for (int i = 0; i < this.dataGridView.SelectedRows.Count; i++)
if (this.dataGridView.SelectedRows[i].Index < this.ColumnGroup.RowCount)
positions.Add(this.dataGridView.SelectedRows[i].Index);
positions.Sort();
}
if (positions.Count != 0) {
this.commandChain.Add(new DeleteRowsCommand(DataSet, this.ColumnGroup.Name, positions));
}
this.dataGridView.ClearSelection();
}
}
#endregion
#region txtColumnName event handler
private void txtColumnName_Leave(object source, EventArgs e) {
this.txtColumnName.Visible = false;
}
private void txtColumnName_KeyDown(object source, KeyEventArgs e) {
if (e.KeyCode != Keys.Enter && e.KeyCode != Keys.Escape)
return;
if (e.KeyCode == Keys.Enter) {
DataGridView.HitTestInfo h = this.dataGridView.HitTest(txtColumnName.Location.X, txtColumnName.Location.Y);
this.commandChain.Add(new RenameColumnCommand(DataSet, this.ColumnGroup.Name, h.ColumnIndex, txtColumnName.Text));
}
this.txtColumnName.Visible = false;
}
#endregion
#region txtColumnGroupName event handler
private void txtColumnGroupName_Click(object sender, EventArgs e) {
bool ctrlPressed = (Control.ModifierKeys & Keys.Control) == Keys.Control;
this.dataGridView.ClearSelection();
this.ColumnGroupActive = !this.ColumnGroupActive;
FireActivated(ctrlPressed);
UpdateStateInformation();
}
private void txtColumnGroupName_DoubleClick(object sender, EventArgs e) {
txtColumnGroupName.ReadOnly = false;
txtColumnGroupName.Text = ColumnGroup.Name;
}
private void txtColumnGroupName_Leave(object sender, EventArgs e) {
if (!txtColumnGroupName.ReadOnly) {
txtColumnGroupName.ReadOnly = true;
if (CheckIfNewColumnGroupNameIsAllowed(txtColumnGroupName.Text))
this.commandChain.Add(new RenameColumnGroupCommand(DataSet, this.ColumnGroup.Name, txtColumnGroupName.Text));
}
}
private void txtColumnGroupName_KeyDown(object sender, KeyEventArgs e) {
if (this.txtColumnGroupName.ReadOnly) //user can not change the name if it is readonly
return;
if (e.KeyCode != Keys.Enter && e.KeyCode != Keys.Escape)
return;
if (e.KeyCode == Keys.Enter && CheckIfNewColumnGroupNameIsAllowed(txtColumnGroupName.Text)) {
this.commandChain.Add(new RenameColumnGroupCommand(DataSet, this.ColumnGroup.Name, txtColumnGroupName.Text));
}
txtColumnGroupName.ReadOnly = true;
this.Focus();
this.Refresh();
}
private bool CheckIfNewColumnGroupNameIsAllowed(string newName) {
return !this.DataSet.ColumnGroups.Any(cg => cg.Name == newName);
}
#endregion
}
}