Skip to content

Instantly share code, notes, and snippets.

@ertugrulozcan
Last active June 24, 2018 01:23
Show Gist options
  • Save ertugrulozcan/124b8f187e9d290ce5e984fab48fe712 to your computer and use it in GitHub Desktop.
Save ertugrulozcan/124b8f187e9d290ce5e984fab48fe712 to your computer and use it in GitHub Desktop.
Telerik RadGridView Excel Costume
<UserControl x:Class="Test.Common.Components.ExcelCostume"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Test.Common.Components"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
IsHitTestVisible="True">
<UserControl.Resources>
<ControlTemplate x:Key="DraggableBorderTemplate" TargetType="{x:Type ContentControl}">
<Border Background="{TemplateBinding Background}" BorderBrush="Green" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsManipulating, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="False">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="2" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsManipulating, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="True">
<Setter Property="Background" Value="#33000000" />
<Setter Property="BorderThickness" Value="3" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="CellClipsTemplate" TargetType="{x:Type UserControl}">
<Border IsManipulationEnabled="True" Width="12" Height="12" Background="Transparent" BorderThickness="0">
<local:Triangle TriangleOrientation="SE" Stroke="Green" Fill="Green" StrokeThickness="1" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Cross" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Resources>
<Grid x:Name="CostumeBorder" VerticalAlignment="Top" HorizontalAlignment="Left">
<ContentControl Template="{StaticResource DraggableBorderTemplate}">
<!--<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="{Binding Path=TestString, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Foreground="AliceBlue" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
<TextBlock Text="{Binding Path=TestString2, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Foreground="AliceBlue" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
</StackPanel>-->
</ContentControl>
<UserControl x:Name="Clips" IsManipulationEnabled="True" Template="{StaticResource CellClipsTemplate}" IsHitTestVisible="True" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Test.Infrastructure.Helpers;
namespace Test.Common.Components
{
/// <summary>
/// Interaction logic for ExcelCostume.xaml
/// </summary>
public partial class ExcelCostume : UserControl, INotifyPropertyChanged
{
#region Fields
private bool isDragging;
private Point dragStartPosition;
private Bounds firstBounds;
private ScanDirection scanDirection;
private TransformGroup transformGroup;
private ScaleTransform scaleTransform;
private TranslateTransform translateTransform;
#endregion
#region Properties
public bool IsManipulating
{
get
{
return isDragging;
}
set
{
this.isDragging = value;
this.RaisePropertyChanged("IsManipulating");
}
}
private Point ManipulationStartPoint { get; set; }
public TransformGroup CostumeBorderTransforms
{
get
{
if (this.transformGroup == null)
{
this.transformGroup = new TransformGroup();
this.translateTransform = new TranslateTransform();
this.transformGroup.Children.Add(this.translateTransform);
this.scaleTransform = new ScaleTransform();
this.transformGroup.Children.Add(this.scaleTransform);
this.CostumeBorder.RenderTransform = this.transformGroup;
}
return this.transformGroup;
}
}
#endregion
#region Dependency Properties
public RadGridView GridView
{
get { return (RadGridView)GetValue(GridViewProperty); }
set { SetValue(GridViewProperty, value); }
}
// Using a DependencyProperty as the backing store for GridView. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridViewProperty =
DependencyProperty.Register("GridView", typeof(RadGridView), typeof(ExcelCostume), new PropertyMetadata(null, OnGridViewChangedCallback));
public bool IsSelectScanningCells
{
get { return (bool)GetValue(IsSelectScanningCellsProperty); }
set { SetValue(IsSelectScanningCellsProperty, value); }
}
// Using a DependencyProperty as the backing store for IsSelectScanningCells. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsSelectScanningCellsProperty =
DependencyProperty.Register("IsSelectScanningCells", typeof(bool), typeof(ExcelCostume), new PropertyMetadata(false));
public string TestString
{
get { return (string)GetValue(TestStringProperty); }
set { SetValue(TestStringProperty, value); }
}
// Using a DependencyProperty as the backing store for TestString. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TestStringProperty =
DependencyProperty.Register("TestString", typeof(string), typeof(ExcelCostume), new PropertyMetadata(null));
public string TestString2
{
get { return (string)GetValue(TestString2Property); }
set { SetValue(TestString2Property, value); }
}
// Using a DependencyProperty as the backing store for TestString2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TestString2Property =
DependencyProperty.Register("TestString2", typeof(string), typeof(ExcelCostume), new PropertyMetadata(null));
#endregion
#region Constructors
public ExcelCostume()
{
InitializeComponent();
this.Loaded += ExcelCostume_Loaded;
}
private void ExcelCostume_Loaded(object sender, RoutedEventArgs e)
{
var createTransforms = this.CostumeBorderTransforms;
this.ConfigureManipulationEvents();
}
#endregion
#region Methods
private void ConfigureManipulationEvents()
{
this.CostumeBorder.MouseLeftButtonDown += new MouseButtonEventHandler(Clips_MouseLeftButtonDown);
this.CostumeBorder.MouseLeftButtonUp += new MouseButtonEventHandler(Clips_MouseLeftButtonUp);
this.CostumeBorder.MouseMove += new MouseEventHandler(Clips_MouseMove);
this.GridView.LostMouseCapture += (sender, e) => { this.IsManipulating = false; };
this.Clips.ManipulationStarting += Clips_ManipulationStarting;
this.Clips.ManipulationStarted += Clips_ManipulationStarted;
this.Clips.ManipulationDelta += Clips_ManipulationDelta;
this.Clips.ManipulationCompleted += Clips_ManipulationCompleted;
}
#endregion
#region Callback Methods
private static void OnGridViewChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var self = d as ExcelCostume;
if (self.GridView != null)
{
if (e.OldValue != null && e.OldValue is RadGridView)
{
var oldGridView = e.OldValue as RadGridView;
oldGridView.CurrentCellChanged -= self.GridView_CurrentCellChanged;
self.GridView.SelectedCellsChanged -= self.GridView_SelectedCellsChanged;
}
if (self.GridView.SelectionMode != SelectionMode.Extended || self.GridView.SelectionUnit != Telerik.Windows.Controls.GridView.GridViewSelectionUnit.Cell)
throw new Exception("SelectionMode is must be 'Extended' and SelectionUnit is must be 'Cell' for ExcelCostume!");
self.GridView.CurrentCellChanged += self.GridView_CurrentCellChanged;
self.GridView.SelectedCellsChanged += self.GridView_SelectedCellsChanged;
}
}
#endregion
#region Mouse Events
private void Clips_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point pt = e.GetPosition(this.Clips);
// Perform the hit test against a given portion of the visual object tree.
HitTestResult result = VisualTreeHelper.HitTest(this.Clips, pt);
if (result != null)
{
this.IsManipulating = true;
var draggableControl = sender as FrameworkElement;
var pointAsClips = e.GetPosition(this.Clips);
var point = e.GetPosition(this);
this.dragStartPosition = new Point(point.X + this.Clips.ActualWidth - pointAsClips.X, point.Y + this.Clips.ActualHeight - pointAsClips.Y);
this.firstBounds = this.GetScannedBounds(draggableControl);
draggableControl.CaptureMouse();
}
}
private void Clips_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.IsManipulating = false;
var draggable = sender as FrameworkElement;
draggable.ReleaseMouseCapture();
this.AutoFillTable(draggable);
}
private void Clips_MouseMove(object sender, MouseEventArgs e)
{
var draggableControl = sender as FrameworkElement;
if (this.IsManipulating && draggableControl != null)
{
Point currentPosition = e.GetPosition(this.Parent as UIElement);
double dragOffsetX = currentPosition.X - dragStartPosition.X;
double dragOffsetY = currentPosition.Y - dragStartPosition.Y;
//this.scanDirection = Math.Abs(dragOffsetY) > Math.Abs(dragOffsetX) ? ScanDirection.Vertical : ScanDirection.Horizontal;
this.scanDirection = this.DetectScanDirection(this.firstBounds, e.GetPosition(this.GridView));
double newWidth = this.firstBounds.Width + dragOffsetX;
double newHeight = this.firstBounds.Height + dragOffsetY;
// Fill to under cell edges
Size differentToEdges = new Size();
var underCell = this.GetCell(currentPosition) as GridViewCell;
if (underCell != null)
{
Point pointAsUnderCell = e.GetPosition(underCell as UIElement);
double differentToEdgesWidth = Math.Abs(underCell.ActualWidth - pointAsUnderCell.X);
double differentToEdgesHeight = Math.Abs(underCell.ActualHeight - pointAsUnderCell.Y);
if (newWidth >= 0)
differentToEdges.Width = differentToEdgesWidth;
else
differentToEdges.Width = underCell.ActualWidth - differentToEdgesWidth;
if (newHeight >= 0)
differentToEdges.Height = differentToEdgesHeight;
else
differentToEdges.Height = underCell.ActualHeight - differentToEdgesHeight;
}
else
{
this.TestString2 = "NULL";
}
if (newWidth >= 0)
{
this.scaleTransform.ScaleX = 1;
this.translateTransform.X = 0;
}
else
{
this.scaleTransform.ScaleX = -1;
this.translateTransform.X = -this.firstBounds.Width;
newWidth -= this.firstBounds.Width;
}
if (underCell != null)
{
if (this.scanDirection == ScanDirection.Horizontal)
draggableControl.Width = Math.Abs(newWidth) + differentToEdges.Width;
else
draggableControl.Width = this.firstBounds.Width;
}
if (newHeight >= 0)
{
this.scaleTransform.ScaleY = 1;
this.translateTransform.Y = 0;
}
else
{
this.scaleTransform.ScaleY = -1;
this.translateTransform.Y = -this.firstBounds.Height;
newHeight -= this.firstBounds.Height;
}
if (underCell != null)
{
if (this.scanDirection == ScanDirection.Vertical)
draggableControl.Height = Math.Abs(newHeight) + differentToEdges.Height;
else
draggableControl.Height = this.firstBounds.Height;
}
}
}
#endregion
#region Manipulation Events
private void Clips_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
this.TestString = "ManipulationStarting";
}
private void Clips_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
this.TestString = "ManipulationStarted";
}
private void Clips_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
this.TestString = "ManipulationDelta (" + e.DeltaManipulation.Translation.X + ", " + e.DeltaManipulation.Translation.Y + ")";
}
private void Clips_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
this.TestString = "ManipulationCompleted";
}
#endregion
#region Scanning Methods
private Bounds GetScannedBounds(FrameworkElement scannedArea)
{
if (scannedArea == null || this.GridView.CurrentCell == null)
{
return new Bounds(0, 0, 0, 0);
}
var orderedSelectedCells = this.GetSelectedCellList();
if (orderedSelectedCells.Count > 0)
{
var point = this.GetCellCoordinate(orderedSelectedCells.First());
if (point != null)
{
Point currentCellCoordinate = point.Value;
int x = (int)(currentCellCoordinate.X - this.translateTransform.X);
if (this.translateTransform.X < 0)
x = x - (int)scannedArea.ActualWidth;
int y = (int)(currentCellCoordinate.Y - this.translateTransform.Y);
if (this.translateTransform.Y < 0)
y = y - (int)scannedArea.ActualHeight;
return new Bounds(x, y, scannedArea.ActualWidth, scannedArea.ActualHeight);
}
}
return new Bounds(0, 0, 0, 0);
}
private ScanDirection DetectScanDirection(Bounds scannedBounds, Point mousePoint)
{
if (mousePoint.X < scannedBounds.LeftTopCorner.X + scannedBounds.Width && mousePoint.X > scannedBounds.LeftTopCorner.X)
{
if (mousePoint.Y < scannedBounds.LeftTopCorner.Y)
return ScanDirection.Up;
else if (mousePoint.Y > scannedBounds.LeftTopCorner.Y + scannedBounds.Height)
return ScanDirection.Down;
}
if (mousePoint.Y < scannedBounds.LeftTopCorner.Y + scannedBounds.Height && mousePoint.Y > scannedBounds.LeftTopCorner.Y)
{
if (mousePoint.X < scannedBounds.LeftTopCorner.X)
return ScanDirection.Left;
else if (mousePoint.X > scannedBounds.LeftTopCorner.X + scannedBounds.Width)
return ScanDirection.Right;
}
Point metacentrePoint = this.FindMetacentre(scannedBounds);
double angle = this.CalculateAngle(metacentrePoint, mousePoint);
this.TestString = angle.ToString("N2");
if (angle >= 45 && angle < 135)
return ScanDirection.Right;
else if (angle >= 135 && angle < 225)
return ScanDirection.Down;
else if (angle >= 225 && angle < 315)
return ScanDirection.Left;
else //if (angle > 315 && angle < 45)
return ScanDirection.Up;
}
private Point FindMetacentre(Bounds bounds)
{
return new Point(bounds.LeftTopCorner.X + bounds.Width / 2, bounds.LeftTopCorner.Y + bounds.Height / 2);
}
private double CalculateAngle(Point origin, Point point)
{
double x = point.X - origin.X;
double y = origin.Y - point.Y;
double angle = Math.Abs(Math.Atan(y / x) * 180 / Math.PI);
if (x >= 0 && y >= 0)
return 90 - angle;
if (x < 0 && y < 0)
return 270 - angle;
if (x <= 0 && y > 0)
return 270 + angle;
if (y <= 0 && x > 0)
return 90 + angle;
return 0;
}
#endregion
#region Auto Fill Methods
private void AutoFillTable(FrameworkElement scannedArea)
{
Bounds bounds = this.GetScannedBounds(scannedArea);
var patternGroup = this.RecognizePattern(this.firstBounds, this.scanDirection);
var filledSeries = this.GenerateFilledSeries(bounds, patternGroup, this.scanDirection);
var targetBounds = bounds - this.firstBounds;
if (targetBounds != null)
{
var targetTable = this.GetTableInBounds(targetBounds);
this.FillTable(filledSeries, targetTable, this.scanDirection);
}
}
private void FillTable(List<double[]> filledSeries, CellTable table, ScanDirection direction)
{
if (direction == ScanDirection.Vertical)
{
for (int columnNo = 0; columnNo < filledSeries.Count; columnNo++)
{
var serie = filledSeries[columnNo];
if (direction == ScanDirection.Up)
serie = serie.Reverse().ToArray();
for (int rowNo = 0; rowNo < serie.Length; rowNo++)
{
table.SetCellValue(rowNo, columnNo, serie[rowNo]);
}
}
}
else
{
for (int rowNo = 0; rowNo < filledSeries.Count; rowNo++)
{
var serie = filledSeries[rowNo];
if (direction == ScanDirection.Left)
serie = serie.Reverse().ToArray();
for (int columnNo = 0; columnNo < serie.Length; columnNo++)
{
table.SetCellValue(rowNo, columnNo, serie[columnNo]);
}
}
}
}
private List<double[]> GenerateFilledSeries(Bounds scannedBounds, PatternGroup patternGroup, ScanDirection direction)
{
List<double[]> filledSeries = new List<double[]>();
var table = this.GetTableInBounds(scannedBounds);
if (table == null || patternGroup == null)
return filledSeries;
int x, y;
if (direction == ScanDirection.Vertical)
{
x = patternGroup.Table.ColumnCount;
y = patternGroup.Table.RowCount;
}
else
{
x = patternGroup.Table.RowCount;
y = patternGroup.Table.ColumnCount;
}
List<double[]> series = new List<double[]>();
for (int i = 0; i < x; i++)
{
series.Add(new double[y]);
for (int j = 0; j < y; j++)
{
if (direction == ScanDirection.Vertical)
{
var cellValue = patternGroup.Table.GetCellValue(j, i, this.GridView.Language.IetfLanguageTag);
if (cellValue != null)
series[i][j] = cellValue.Value;
}
else
{
var cellValue = patternGroup.Table.GetCellValue(i, j, this.GridView.Language.IetfLanguageTag);
if (cellValue != null)
series[i][j] = cellValue.Value;
}
}
}
int fillLength = 0;
bool isInversed = false;
Point sourcePoint = patternGroup.Table.GetCellLocation(0, 0, this.GridView);
Point targetPoint = table.GetCellLocation(0, 0, this.GridView);
if (direction == ScanDirection.Vertical)
{
if (sourcePoint.X > targetPoint.X)
{
isInversed = true;
fillLength = (int)sourcePoint.X - (int)targetPoint.X;
}
else
{
isInversed = false;
fillLength = table.RowCount - patternGroup.Table.RowCount;
}
}
else
{
if (sourcePoint.Y > targetPoint.Y)
{
isInversed = true;
fillLength = (int)sourcePoint.Y - (int)targetPoint.Y;
}
else
{
isInversed = false;
fillLength = table.ColumnCount - patternGroup.Table.ColumnCount;
}
}
if (fillLength <= 0)
return filledSeries;
int patternNo = 0;
foreach (var pattern in patternGroup.Patterns)
{
if (!isInversed)
{
var serie = pattern.GenerateSerie(series[patternNo], fillLength);
filledSeries.Add(serie);
}
else
{
var serie = pattern.GenerateInverseSerie(series[patternNo], fillLength);
filledSeries.Add(serie);
}
patternNo++;
}
return filledSeries;
}
#endregion
#region Manipulation Methods
private new void ManipulationStarting(MouseDevice mouse)
{
}
private new void ManipulationStarted(MouseDevice mouse)
{
this.IsManipulating = true;
this.ManipulationStartPoint = mouse.GetPosition(this.GridView);
}
private new void ManipulationDelta(MouseDevice mouse)
{
Point mousePosition = mouse.GetPosition(this.GridView);
double deltaX = mousePosition.X - this.ManipulationStartPoint.X;
double deltaY = mousePosition.Y - this.ManipulationStartPoint.Y;
double newWidth = this.CostumeBorder.Width + deltaX;
if (newWidth >= 0.0d)
this.CostumeBorder.Width = newWidth;
double newHeight = this.CostumeBorder.Height + deltaY;
if (newHeight >= 0.0d)
this.CostumeBorder.Height = newHeight;
}
private void ManipulationComplete(MouseDevice mouse)
{
this.IsManipulating = false;
}
#endregion
#region Pattern Recognition Methods
private PatternGroup RecognizePattern(Bounds bounds, ScanDirection direction)
{
var table = this.GetTableInBounds(bounds);
if (table == null)
return null;
int x, y;
if (direction == ScanDirection.Vertical)
{
x = table.ColumnCount;
y = table.RowCount;
}
else
{
x = table.RowCount;
y = table.ColumnCount;
}
IAutoFillPattern[] patterns = new IAutoFillPattern[x];
if (y == 1)
{
for (int i = 0; i < x; i++)
patterns[i] = new IncrementalPattern(0.0d);
return new PatternGroup(patterns, table);
}
if (y == 2)
{
for (int i = 0; i < x; i++)
{
double? value1, value2;
if (direction == ScanDirection.Vertical)
{
value1 = table.GetCellValue(0, i, this.GridView.Language.IetfLanguageTag);
value2 = table.GetCellValue(1, i, this.GridView.Language.IetfLanguageTag);
}
else
{
value1 = table.GetCellValue(i, 0, this.GridView.Language.IetfLanguageTag);
value2 = table.GetCellValue(i, 1, this.GridView.Language.IetfLanguageTag);
}
if (value1 != null && value2 != null)
patterns[i] = new IncrementalPattern(value2.Value - value1.Value);
else
patterns[i] = new IrregularPattern();
}
return new PatternGroup(patterns, table);
}
for (int i = 0; i < x; i++)
{
bool isIncremental = false;
double diff = 0.0d;
for (int j = 1; j < y - 1; j++)
{
double? value1, value2, value3;
if (direction == ScanDirection.Vertical)
{
value1 = table.GetCellValue(j - 1, i, this.GridView.Language.IetfLanguageTag);
value2 = table.GetCellValue(j, i, this.GridView.Language.IetfLanguageTag);
value3 = table.GetCellValue(j + 1, i, this.GridView.Language.IetfLanguageTag);
}
else
{
value1 = table.GetCellValue(i, j - 1, this.GridView.Language.IetfLanguageTag);
value2 = table.GetCellValue(i, j, this.GridView.Language.IetfLanguageTag);
value3 = table.GetCellValue(i, j + 1, this.GridView.Language.IetfLanguageTag);
}
if (value1 != null && value2 != null && value3 != null)
{
diff = value3.Value - value2.Value;
if (diff == value2.Value - value1.Value)
{
isIncremental = true;
continue;
}
else
{
isIncremental = false;
break;
}
}
}
if (isIncremental)
patterns[i] = new IncrementalPattern(diff);
else
patterns[i] = new IrregularPattern();
}
return new PatternGroup(patterns, table);
}
#endregion
#region GridView Events
private void GridView_CurrentCellChanged(object sender, GridViewCurrentCellChangedEventArgs e)
{
if (e.NewCell != null)
{
string cellValue = e.NewCell.DataContext.ToString();
if (e.NewCell.Content is Control)
cellValue = (e.NewCell.Content as Control).DataContext.ToString();
this.scaleTransform.ScaleX = 1;
this.scaleTransform.ScaleY = 1;
this.translateTransform.X = 0;
this.translateTransform.Y = 0;
}
}
private void GridView_SelectedCellsChanged(object sender, Telerik.Windows.Controls.GridView.GridViewSelectedCellsChangedEventArgs e)
{
if (this.GridView.SelectedCells.Count > 0)
{
var orderedSelectedCells = this.GetSelectedCellList();
var leftTopCellPoint = this.GetCellCoordinate(orderedSelectedCells.FirstOrDefault());
if (leftTopCellPoint != null)
{
this.CostumeBorder.Margin = new Thickness(leftTopCellPoint.Value.X, leftTopCellPoint.Value.Y, 0, 0);
var lastCell = this.GetCell(orderedSelectedCells.Last());
if (lastCell != null)
{
var rightBottomCellPoint = this.GetCellCoordinate(orderedSelectedCells.Last());
if (rightBottomCellPoint != null)
{
double width = rightBottomCellPoint.Value.X - leftTopCellPoint.Value.X + lastCell.ActualWidth;
if (width >= 0)
this.CostumeBorder.Width = width;
double height = rightBottomCellPoint.Value.Y - leftTopCellPoint.Value.Y + lastCell.ActualHeight;
if (height >= 0)
this.CostumeBorder.Height = height;
}
}
}
}
}
#endregion
#region Helper Methods
private GridViewCellBase GetCell(GridViewCellInfo cellInfo)
{
if (cellInfo == null || cellInfo.Item == null)
return null;
var cellContainer = this.GridView.ItemContainerGenerator.ContainerFromItem(cellInfo.Item);
if (cellContainer == null || !(cellContainer is GridViewRow))
return null;
var row = cellContainer as GridViewRow;
var cell = row.Cells[cellInfo.Column.DisplayIndex];
return cell;
}
private Point? GetCellCoordinate(GridViewCellInfo cellInfo)
{
var cell = this.GetCell(cellInfo);
if (cell == null)
return null;
return cell.TranslatePoint(new Point(0, 0), this.GridView);
}
private double GetCellCoordinateDistance(GridViewCellInfo cellInfo)
{
var point = this.GetCellCoordinate(cellInfo);
if (point != null)
return point.Value.X * point.Value.Y;
else
return 0;
}
private GridViewCellBase GetCell(Point point)
{
foreach (var item in this.GridView.Items)
{
var cellContainer = this.GridView.ItemContainerGenerator.ContainerFromItem(item);
if (cellContainer != null && cellContainer is GridViewRow)
{
var row = cellContainer as GridViewRow;
foreach (var cell in row.Cells)
{
Point cellPoint = cell.TranslatePoint(new Point(0, 0), this.GridView);
if (this.IsInBounds(point, cellPoint, cell.ActualWidth, cell.ActualHeight))
{
return cell;
}
}
}
}
return null;
}
private List<GridViewCellInfo> GetSelectedCellList()
{
if (this.GridView.SelectedCells.Count <= 0)
return new List<GridViewCellInfo>();
var selectedCells = this.GridView.SelectedCells.Where(x => x.Item != null).ToList();
var orderedSelectedCells = selectedCells.OrderBy(x => this.GetCellCoordinateDistance(x)).ToList();
return orderedSelectedCells;
}
private bool IsInBounds(Point point, Point boundStartPoint, double boundWidth, double boundHeight)
{
return (point.X >= boundStartPoint.X && point.X < (boundStartPoint.X + boundWidth)) &&
(point.Y >= boundStartPoint.Y && point.Y < (boundStartPoint.Y + boundHeight));
}
private List<GridViewCellBase> GetCellsInBounds(Bounds bounds)
{
var cells = new List<GridViewCellBase>();
int startX = (int)bounds.LeftTopCorner.X + 3;
int startY = (int)bounds.LeftTopCorner.Y + 3;
var leftTopCell = this.GetCell(new Point(startX, startY));
int endX = (int)(bounds.LeftTopCorner.X + bounds.Width) - 3;
int endY = (int)(bounds.LeftTopCorner.Y + bounds.Height) - 3;
var rightBottomCell = this.GetCell(new Point(endX, endY));
if (leftTopCell != null && rightBottomCell != null)
{
int firstRowIndex = this.GridView.ItemContainerGenerator.IndexFromContainer(leftTopCell.ParentRow);
int lastRowIndex = this.GridView.ItemContainerGenerator.IndexFromContainer(rightBottomCell.ParentRow);
for (int i = firstRowIndex; i <= lastRowIndex; i++)
{
var cellContainer = this.GridView.ItemContainerGenerator.ContainerFromIndex(i);
if (cellContainer != null && cellContainer is GridViewRow)
{
var row = cellContainer as GridViewRow;
for (int columnNo = leftTopCell.Column.DisplayIndex; columnNo <= rightBottomCell.Column.DisplayIndex; columnNo++)
{
cells.Add(row.Cells[columnNo]);
}
}
}
}
return cells;
}
private CellTable GetTableInBounds(Bounds bounds)
{
if (bounds == null)
return null;
int startX = (int)bounds.LeftTopCorner.X + 3;
int startY = (int)bounds.LeftTopCorner.Y + 3;
var leftTopCell = this.GetCell(new Point(startX, startY));
int endX = (int)(bounds.LeftTopCorner.X + bounds.Width) - 3;
int endY = (int)(bounds.LeftTopCorner.Y + bounds.Height) - 3;
var rightBottomCell = this.GetCell(new Point(endX, endY));
if (leftTopCell != null && rightBottomCell != null)
{
int firstRowIndex = this.GridView.ItemContainerGenerator.IndexFromContainer(leftTopCell.ParentRow);
int lastRowIndex = this.GridView.ItemContainerGenerator.IndexFromContainer(rightBottomCell.ParentRow);
int columnCount = rightBottomCell.Column.DisplayIndex - leftTopCell.Column.DisplayIndex + 1;
int rowCount = lastRowIndex - firstRowIndex + 1;
CellTable table = new CellTable(rowCount, columnCount);
for (int i = firstRowIndex; i <= lastRowIndex; i++)
{
var cellContainer = this.GridView.ItemContainerGenerator.ContainerFromIndex(i);
if (cellContainer != null && cellContainer is GridViewRow)
{
var row = cellContainer as GridViewRow;
for (int columnNo = leftTopCell.Column.DisplayIndex; columnNo <= rightBottomCell.Column.DisplayIndex; columnNo++)
{
table.SetCell(row.Cells[columnNo], i - firstRowIndex, columnNo - leftTopCell.Column.DisplayIndex);
}
}
}
return table;
}
return null;
}
#endregion
#region Manipulation Classes
public class ScanDirection : IEquatable<ScanDirection>
{
private ScanOrientation direction;
private enum ScanOrientation
{
Up,
Down,
Right,
Left,
Vertical,
Horizontal
}
private static ScanDirection up = new ScanDirection(ScanOrientation.Up);
private static ScanDirection down = new ScanDirection(ScanOrientation.Down);
private static ScanDirection right = new ScanDirection(ScanOrientation.Right);
private static ScanDirection left = new ScanDirection(ScanOrientation.Left);
private static ScanDirection vertical = new ScanDirection(ScanOrientation.Vertical);
private static ScanDirection horizontal = new ScanDirection(ScanOrientation.Horizontal);
public static ScanDirection Up { get { return ScanDirection.up; } }
public static ScanDirection Down { get { return ScanDirection.down; } }
public static ScanDirection Right { get { return ScanDirection.right; } }
public static ScanDirection Left { get { return ScanDirection.left; } }
public static ScanDirection Vertical { get { return ScanDirection.vertical; } }
public static ScanDirection Horizontal { get { return ScanDirection.horizontal; } }
private ScanDirection(ScanOrientation direction)
{
this.direction = direction;
}
private static bool IsEquals(ScanDirection obj1, ScanDirection obj2)
{
if (obj1.direction == obj2.direction)
return true;
switch (obj1.direction)
{
case ScanOrientation.Up:
case ScanOrientation.Down:
return obj2.direction == ScanOrientation.Vertical;
case ScanOrientation.Right:
case ScanOrientation.Left:
return obj2.direction == ScanOrientation.Horizontal;
case ScanOrientation.Vertical:
return obj2.direction == ScanOrientation.Up || obj2.direction == ScanOrientation.Down;
case ScanOrientation.Horizontal:
return obj2.direction == ScanOrientation.Right || obj2.direction == ScanOrientation.Left;
}
return false;
}
public bool Equals(ScanDirection other)
{
return IsEquals(this, other);
}
public override bool Equals(object obj)
{
if (obj is ScanDirection)
return IsEquals(this, obj as ScanDirection);
return false;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public static bool operator ==(ScanDirection obj1, ScanDirection obj2)
{
return IsEquals(obj1, obj2);
}
// this is second one '!='
public static bool operator !=(ScanDirection obj1, ScanDirection obj2)
{
return !IsEquals(obj1, obj2);
}
}
#endregion
#region Table Classes
private class Bounds
{
public Point LeftTopCorner { get; private set; }
public double Width { get; private set; }
public double Height { get; private set; }
public Bounds(Point point, double width, double height)
{
this.LeftTopCorner = point;
this.Width = width;
this.Height = height;
}
public Bounds(int x, int y, double width, double height)
{
this.LeftTopCorner = new Point(x, y);
this.Width = width;
this.Height = height;
}
public static Bounds operator -(Bounds bounds1, Bounds bounds2)
{
if (bounds1 == null || bounds2 == null)
return null;
if (bounds1.Width == bounds2.Width)
{
if (bounds1.Height >= bounds2.Height)
{
if (bounds1.LeftTopCorner.Y < bounds2.LeftTopCorner.Y)
{
return new Bounds((int)bounds1.LeftTopCorner.X, (int)bounds1.LeftTopCorner.Y, bounds1.Width, bounds1.Height - bounds2.Height);
}
else
{
return new Bounds((int)bounds1.LeftTopCorner.X, (int)bounds1.LeftTopCorner.Y + (int)bounds2.Height, bounds1.Width, bounds1.Height - bounds2.Height);
}
}
else
{
//throw new Exception("Bounds2 > Bounds1");
return null;
}
}
else if (bounds1.Height == bounds2.Height)
{
if (bounds1.Width >= bounds2.Width)
{
if (bounds1.LeftTopCorner.X < bounds2.LeftTopCorner.X)
{
return new Bounds((int)bounds1.LeftTopCorner.X, (int)bounds1.LeftTopCorner.Y, bounds1.Width - bounds2.Width, bounds1.Height);
}
else
{
return new Bounds((int)bounds1.LeftTopCorner.X + (int)bounds2.Width, (int)bounds1.LeftTopCorner.Y, bounds1.Width - bounds2.Width, bounds1.Height);
}
}
else
{
//throw new Exception("Bounds2 > Bounds1");
return null;
}
}
else
{
//throw new Exception("Bounds sizes not compatible for extraction!");
return null;
}
}
}
private class CellTable
{
public int RowCount { get; private set; }
public int ColumnCount { get; private set; }
private GridViewCellBase[,] Table { get; set; }
public CellTable(int rowCount, int columnCount)
{
this.RowCount = rowCount;
this.ColumnCount = columnCount;
this.Table = new GridViewCellBase[columnCount, rowCount];
}
public void SetCell(GridViewCellBase cellBase, int rowNo, int columnNo)
{
if ((rowNo < 0 || rowNo >= this.RowCount) || (columnNo < 0 || columnNo >= this.ColumnCount))
return; // throw new IndexOutOfRangeException();
this.Table[columnNo, rowNo] = cellBase;
}
public void SetCellValue(int rowNo, int columnNo, double value)
{
if ((rowNo < 0 || rowNo >= this.RowCount) || (columnNo < 0 || columnNo >= this.ColumnCount))
return; // throw new IndexOutOfRangeException();
var cellBase = this.Table[columnNo, rowNo];
if (cellBase is GridViewCell)
{
var cell = cellBase as GridViewCell;
cell.ParentRow.Item.GetType().GetProperty(cell.DataColumn.DataMemberBinding.Path.Path).SetValue(cell.ParentRow.Item, value, null);
//cell.Value = value;
//cell.IsSelected = true;
}
}
public GridViewCellBase GetCell(int rowNo, int columnNo)
{
if ((rowNo < 0 || rowNo >= this.RowCount) || (columnNo < 0 || columnNo >= this.ColumnCount))
return null; // throw new IndexOutOfRangeException();
return this.Table[columnNo, rowNo];
}
public double? GetCellValue(int i, int j, string cultureTag)
{
GridViewCellBase cellBase = this.GetCell(i, j);
if (cellBase is GridViewCell)
{
var cell = cellBase as GridViewCell;
if (ReflectionHelper.IsNumericType(cell.Value))
{
double cellValue = Convert.ToDouble(cell.Value);
return cellValue;
}
else
{
double cellValue = 0.0d;
bool isParsed = DoubleParsingHelper.TryParse(cell.Value.ToString(), cultureTag, out cellValue);
if (isParsed)
return cellValue;
else
return null;
}
}
return null;
}
public Point GetCellLocation(int i, int j, RadGridView gridView)
{
var firstCellOfSource = this.GetCell(i, j);
int rowIndex = gridView.ItemContainerGenerator.IndexFromContainer(firstCellOfSource.ParentRow);
int columnIndex = firstCellOfSource.Column.DisplayIndex;
return new Point(rowIndex, columnIndex);
}
}
#endregion
#region Pattern Classes
private class PatternGroup
{
private IAutoFillPattern[] patterns;
private CellTable table;
public IAutoFillPattern[] Patterns
{
get
{
return patterns;
}
private set
{
this.patterns = value;
}
}
public CellTable Table
{
get
{
return table;
}
private set
{
this.table = value;
}
}
public PatternGroup(IAutoFillPattern[] patterns, CellTable table)
{
this.Patterns = patterns;
this.Table = table;
}
}
private interface IAutoFillPattern
{
double[] GenerateSerie(double[] sourceSerie, int serieLength);
double[] GenerateInverseSerie(double[] sourceSerie, int serieLength);
}
private class IncrementalPattern : IAutoFillPattern
{
public double Increase { get; private set; }
public IncrementalPattern(double increase)
{
this.Increase = increase;
}
public double[] GenerateSerie(double[] sourceSerie, int serieLength)
{
double[] serie = new double[serieLength];
double lastValue = sourceSerie.Last();
for (int i = 0; i < serieLength; i++)
{
serie[i] = lastValue + this.Increase * (i + 1);
}
return serie;
}
public double[] GenerateInverseSerie(double[] sourceSerie, int serieLength)
{
double[] serie = new double[serieLength];
double firstValue = sourceSerie.First();
for (int i = 0; i < serieLength; i++)
{
serie[i] = firstValue - this.Increase * (i + 1);
}
return serie;
}
}
private class IrregularPattern : IAutoFillPattern
{
public double[] GenerateSerie(double[] sourceSerie, int serieLength)
{
double[] serie = new double[serieLength];
for (int i = 0; i < serieLength; i++)
{
serie[i] = sourceSerie[i % sourceSerie.Length];
}
return serie;
}
public double[] GenerateInverseSerie(double[] sourceSerie, int serieLength)
{
var inversedSourceSerie = sourceSerie.Reverse();
return this.GenerateSerie(inversedSourceSerie.ToArray(), serieLength);
}
}
#endregion
#region RaisePropertyChanged
/// <summary>
/// Helper to set dependency property value.
/// </summary>
/// <typeparam name="T">Property type</typeparam>
/// <param name="target">Target Dependency property</param>
/// <param name="value">Value to set</param>
/// <param name="changedProperties">argument list on changed property names we going notify about notify</param>
/// <returns></returns>
protected virtual bool SetValue<T>(ref T target, T value, params string[] changedProperties)
{
if (Object.Equals(target, value))
{
return false; // no changes, same value
}
target = value;
foreach (string property in changedProperties)
{
RaisePropertyChanged(property);
}
return true;
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment