/// <summary>
 ///     Sets the content of a <see cref="T:System.Windows.Controls.Border" /> element used to display the value of a data
 ///     cell.
 /// </summary>
 /// <param name="grid">
 ///     <see cref="T:C1.WPF.FlexGrid.C1FlexGrid" /> that owns the cell.
 /// </param>
 /// <param name="bdr">
 ///     <see cref="T:System.Windows.Controls.Border" /> element that contains the header.
 /// </param>
 /// <param name="rng">
 ///     <see cref="T:C1.WPF.FlexGrid.CellRange" /> that specifies the row and column represented by the cell.
 /// </param>
 public virtual void CreateCellContentEditor(C1FlexGrid grid, Border bdr, CellRange rng)
 {
     Row row = grid.Rows[rng.Row];
     Column column = grid.Columns[rng.Column];
     GroupRow groupRow = row as GroupRow;
     if (row.DataItem != null)
     {
         DataTemplate template = (column.CellEditingTemplate ?? column.CellTemplate);
         if (template != null)
         {
             bdr.Padding = GetTemplatePadding(bdr.Padding);
             bdr.Child = GetTemplatedCell(grid, template);
             return;
         }
     }
     Brush editorForeground = grid.EditorForeground ?? grid.CursorForeground ?? grid.SelectionForeground;
     Binding binding = column.GetEditBinding(grid.Rows[rng.Row]);
     if (grid.EditableCollectionView != null && Equals(bdr.DataContext, grid.EditableCollectionView.CurrentAddItem))
     {
         binding = Util.Util.CloneBinding(binding);
         Util.Util.SetBindingValidation(binding, false);
     }
     bool gridHasChildren = grid.GetChildItemsPropertyInfo() != null;
     Type dataType = column.DataType;
     if ((groupRow == null || gridHasChildren) && (dataType == typeof (bool) || dataType == typeof (bool?)))
     {
         CheckBox cb = new CheckBox();
         cb.IsThreeState = dataType == typeof (bool?);
         cb.HorizontalAlignment = HorizontalAlignment.Center;
         cb.VerticalAlignment = VerticalAlignment.Center;
         if (editorForeground != null)
         {
             cb.Foreground = editorForeground;
         }
         bdr.Child = cb;
         if (binding != null)
         {
             cb.SetBinding(ToggleButton.IsCheckedProperty, binding);
         }
         cb.FocusVisualStyle = null;
     }
     else
     {
         C1FlexComboBox comboBox = new C1FlexComboBox();
         comboBox.VerticalAlignment = VerticalAlignment.Center;
         if (editorForeground != null)
         {
             comboBox.Foreground = editorForeground;
         }
         bdr.Child = comboBox;
         Thickness padding = bdr.Padding;
         Thickness thickness = bdr.Padding;
         bdr.Padding = new Thickness(padding.Left - 2, 0, thickness.Right - 2, 0);
         if (binding == null)
         {
             object obj = grid[rng.Row, rng.Column];
             if (obj != null)
             {
                 comboBox.Text = obj.ToString();
             }
         }
         else
         {
             comboBox.SetBinding(TextBox.TextProperty, binding);
         }
         IEditValueConverter converter = column.ValueConverter as IEditValueConverter;
         if (converter != null)
         {
             comboBox.DropDownItems = converter.Values;
             comboBox.IsEditable = !converter.Exclusive;
         }
     }
     ApplyCellStyles(grid, grid.Cells, rng, bdr, true);
 }
 /// <summary>
 ///     Gets a <see cref="T:C1.WPF.FlexGrid.CellRange" /> that specifies the merged extent of a cell
 ///     in a <see cref="T:C1.WPF.FlexGrid.GridPanel" />.
 /// </summary>
 /// <param name="grid">
 ///     <see cref="T:C1.WPF.FlexGrid.C1FlexGrid" /> that contains the merged cell.
 /// </param>
 /// <param name="cellType">
 ///     <see cref="T:C1.WPF.FlexGrid.CellType" /> that specifies the type of the merged cell.
 /// </param>
 /// <param name="rng">A <see cref="T:C1.WPF.FlexGrid.CellRange" /> that specifies the coordinates of the cell to be merged.</param>
 /// <returns>
 ///     A <see cref="T:C1.WPF.FlexGrid.CellRange" /> that expands the given <paramref name="rng" /> over a merged
 ///     range.
 /// </returns>
 /// <remarks>
 ///     This method expands ranges by comparing the cell contents with the content of neighboring
 ///     cells and merging cells that have the same content.
 /// </remarks>
 public virtual CellRange GetMergedRange(C1FlexGrid grid, CellType cellType, CellRange rng)
 {
     switch (cellType)
     {
         case CellType.Cell:
         {
             if (grid.ActiveEditor != null && grid.EditorRange.Contains(rng))
             {
                 return grid.EditorRange;
             }
             if (grid.GetChildItemsPropertyInfo() != null)
             {
                 return rng;
             }
             return GetMergedRange(grid, grid.Cells, rng);
         }
         case CellType.ColumnHeader:
         {
             return GetMergedRange(grid, grid.ColumnHeaders, rng);
         }
         case CellType.RowHeader:
         {
             return GetMergedRange(grid, grid.RowHeaders, rng);
         }
         case CellType.TopLeft:
         {
             return GetMergedRange(grid, grid.TopLeftCells, rng);
         }
     }
     return rng;
 }
 /// <summary>
 ///     Gets a <see cref="T:System.Windows.Thickness" /> value that represents the thickness of the cell borders.
 /// </summary>
 /// <param name="grid">
 ///     <see cref="T:C1.WPF.FlexGrid.C1FlexGrid" /> that owns the cell.
 /// </param>
 /// <param name="rng">
 ///     <see cref="T:C1.WPF.FlexGrid.CellRange" /> that specifies the row and column represented by the cell.
 /// </param>
 /// <returns>A <see cref="T:System.Windows.Thickness" /> value that represents the thickness of the cell borders.</returns>
 public virtual Thickness GetBorderThickness(C1FlexGrid grid, CellRange rng)
 {
     switch (grid.GridLinesVisibility)
     {
         case GridLinesVisibility.None:
             return _bdrN;
         case GridLinesVisibility.Horizontal:
             return _bdrH;
         case GridLinesVisibility.Vertical:
             if (!(grid.Rows[rng.Row] is GroupRow) || grid.GetChildItemsPropertyInfo() != null)
             {
                 return _bdrV;
             }
             return _bdrA;
         default:
             return _bdrA;
     }
 }
 /// <summary>
 ///     Sets the content of a <see cref="T:System.Windows.Controls.Border" /> element used to display the value of a column
 ///     header cell.
 /// </summary>
 /// <param name="grid">
 ///     <see cref="T:C1.WPF.FlexGrid.C1FlexGrid" /> that owns the cell.
 /// </param>
 /// <param name="bdr">
 ///     <see cref="T:System.Windows.Controls.Border" /> element that contains the header.
 /// </param>
 /// <param name="rng">
 ///     <see cref="T:C1.WPF.FlexGrid.CellRange" /> that specifies the row and column represented by the cell.
 /// </param>
 public virtual void CreateColumnHeaderContent(C1FlexGrid grid, Border bdr, CellRange rng)
 {
     TextBlock tb = new TextBlock();
     tb.VerticalAlignment = VerticalAlignment.Center;
     bdr.Child = tb;
     object columnHeader = grid.ColumnHeaders[rng.Row, rng.Column];
     if (columnHeader != null)
     {
         tb.Text = columnHeader.ToString();
     }
     if (string.IsNullOrEmpty(tb.Text) && rng.Row == 0)
     {
         tb.Text = grid.Columns[rng.Column].GetHeader() ?? string.Empty;
     }
     if (grid.ColumnHeaderForeground != null)
     {
         tb.Foreground = grid.ColumnHeaderForeground;
     }
     if (grid.HeaderFontWeight.HasValue)
     {
         tb.FontWeight = grid.HeaderFontWeight.Value;
     }
     Column column = grid.Columns[rng.Column];
     if (column.HeaderTemplate != null)
     {
         bdr.Padding = GetTemplatePadding(bdr.Padding);
         bdr.Child = GetTemplatedCell(grid, column.HeaderTemplate);
     }
     ApplyCellStyles(grid, grid.ColumnHeaders, rng, bdr, false);
     ToolTipService.SetToolTip(bdr, column.ToolTip);
     if (grid.ShowSort && IsSortSymbolRow(grid, rng))
     {
         C1FlexGrid fg = grid.Columns.Count > 0 ? grid.Columns[0].Grid : grid;
         ListSortDirection? columnSort = fg.GetColumnSort(rng.Column);
         if (columnSort.HasValue)
         {
             FrameworkElement glyphSort = GetGlyphSort(columnSort.Value, tb.Foreground);
             SetBorderContent(bdr, bdr.Child, glyphSort, 1);
         }
     }
     if (grid.ShowOutlineBar && rng.Row == grid.ColumnHeaders.Rows.Count - 1 && rng.Column <= grid.Columns.FirstVisibleIndex)
     {
         int level = grid.Rows.MaxGroupLevel + 1;
         if (grid.GetChildItemsPropertyInfo() != null)
         {
             level--;
         }
         if (level > 0)
         {
             BuildOutlineBar(bdr, grid, level);
         }
     }
 }
 private void CreateCellContent(C1FlexGrid grid, GridPanel panel, Border bdr, CellRange rng)
 {
     Row row = panel.Rows[rng.Row];
     Column col = panel.Columns[rng.Column];
     GroupRow groupRow = row as GroupRow;
     if (row.DataItem != null && col.CellTemplate != null && panel.CellType == CellType.Cell)
     {
         bdr.Padding = GetTemplatePadding(bdr.Padding);
         bdr.Child = GetTemplatedCell(grid, col.CellTemplate);
         ApplyCellStyles(grid, panel, rng, bdr, false);
         AddTreeIcon(grid, rng, bdr);
         return;
     }
     Binding binding = row.DataItem != null ? col.Binding : null;
     object obj = (row.DataItem != null ? null : panel[rng.Row, rng.Column]);
     bool gridHasChildren = grid.GetChildItemsPropertyInfo() != null;
     if (groupRow != null && groupRow.Group != null && obj == null && !gridHasChildren && rng.Column <= grid.Columns.FirstVisibleIndex)
     {
         binding = new Binding();
         binding.Source = groupRow.Group;
         binding.Converter = grid.GetGroupHeaderConverter();
         binding.ConverterParameter = row;
     }
     Brush foreground = GetForegroundBrush(grid, row, grid.Foreground);
     Type dataType = col.DataType;
     TextBlock tb = null;
     if ((groupRow == null || gridHasChildren) && panel.CellType == CellType.Cell && (dataType == typeof (bool) || dataType == typeof (bool?)))
     {
         CheckBox cb = new CheckBox();
         cb.IsThreeState = (dataType == typeof (bool?));
         cb.HorizontalAlignment = HorizontalAlignment.Center;
         cb.VerticalAlignment = VerticalAlignment.Center;
         cb.IsHitTestVisible = false;
         cb.IsTabStop = false;
         if (foreground != null)
         {
             cb.Foreground = foreground;
         }
         bdr.Child = cb;
         if (binding == null)
         {
             cb.IsChecked = obj as bool?;
         }
         else
         {
             cb.SetBinding(ToggleButton.IsCheckedProperty, binding);
         }
         bdr.MouseLeftButtonDown += bdr_MouseLeftButtonDown;
     }
     else
     {
         tb = new TextBlock();
         tb.VerticalAlignment = VerticalAlignment.Center;
         if (foreground != null)
         {
             tb.Foreground = foreground;
         }
         bdr.Child = tb;
         if (binding != null)
         {
             tb.SetBinding(TextBlock.TextProperty, binding);
             if (AlignRight(row, col, col.DataType))
             {
                 tb.HorizontalAlignment = HorizontalAlignment.Right;
                 tb.TextAlignment = TextAlignment.Right;
             }
         }
         else if (obj != null)
         {
             tb.Text = row.GetDataFormatted(col);
             if (AlignRight(row, col, obj.GetType()))
             {
                 tb.HorizontalAlignment = HorizontalAlignment.Right;
                 tb.TextAlignment = TextAlignment.Right;
             }
         }
     }
     ApplyCellStyles(grid, panel, rng, bdr, false);
     if (panel.CellType == CellType.Cell)
     {
         AddTreeIcon(grid, rng, bdr);
         if (tb != null && grid.AllowEditing(rng.Row, rng.Column))
         {
             ColumnValueConverter converter = col.ValueConverter as ColumnValueConverter;
             if (converter != null && converter.Values != null && converter.Values.Count > 0)
             {
                 ShowDropDownButton(grid, bdr);
             }
         }
     }
 }