/// <summary>
        /// Inserts item to <see cref="DataGrid" />.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="index">The index.</param>
        /// <returns>
        /// Returns <c>true</c> if insertion is successful, <c>false</c> otherwise.
        /// </returns>
        public override bool InsertItem(DataGrid owner,  int index)
        {
            var list = owner.ItemsSource;
            if (list == null)
            {
                return false;
            }

            var itemType = TypeHelper.GetItemType(list);

            var newList = owner.CreateInstance(itemType) as IList;

            var innerType = TypeHelper.GetInnerTypeOfList(list);
            if (innerType == null)
            {
                return false;
            }

            if (owner.ItemsInRows)
            {
                if (newList != null)
                {
                    for (var ii = 0; ii < owner.Columns; ii++)
                    {
                        newList.Add(owner.CreateInstance(innerType));
                    }

                    if (index < 0)
                    {
                        list.Add(newList);
                    }
                    else
                    {
                        list.Insert(index, newList);
                    }
                }
            }
            else
            {
                // insert/append one new element to each list.
                foreach (var row in list.OfType<IList>())
                {
                    var newItem = owner.CreateInstance(innerType);
                    if (index < 0)
                    {
                        row.Add(newItem);
                    }
                    else
                    {
                        row.Insert(index, newItem);
                    }
                }
            }

            return true;
        }
 /// <summary>
 /// Creates the cell definition for the specified cell.
 /// </summary>
 /// <param name="owner">The owner.</param>
 /// <param name="cell">The cell.</param>
 /// <returns>
 /// The cell definition
 /// </returns>
 public virtual CellDefinition CreateCellDefinition(
     DataGrid owner,
     CellRef cell)
 {
     var pd = owner.GetPropertyDefinition(cell);
     var item = owner.Operator.GetItem(owner, cell);
     var cd = this.CreateCellDefinitionOverride(owner, cell, pd, item);
     this.ApplyProperties(cd, owner, cell, pd, item);
     return cd;
 }
        /// <summary>
        /// Creates the cell definition object.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell.</param>
        /// <param name="pd">The property definition.</param>
        /// <param name="item">The item.</param>
        /// <returns>A cell definition.</returns>
        protected virtual CellDefinition CreateCellDefinitionOverride(DataGrid owner, CellRef cell, PropertyDefinition pd, object item)
        {
            var propertyType = owner.Operator.GetPropertyType(pd, cell, item);

            var tcd = pd as TemplateColumnDefinition;
            if (tcd != null)
            {
                return new TemplateCellDefinition
                {
                    DisplayTemplate = tcd.CellTemplate,
                    EditTemplate = tcd.CellEditingTemplate
                };
            }

            if (propertyType.Is(typeof(bool)))
            {
                return new CheckCellDefinition();
            }

            if (propertyType.Is(typeof(Color)))
            {
                return new ColorCellDefinition();
            }

            if (propertyType.Is(typeof(Enum)))
            {
                var enumType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
                var values = Enum.GetValues(enumType).Cast<object>().ToList();
                if (Nullable.GetUnderlyingType(propertyType) != null)
                {
                    values.Insert(0, null);
                }

                return new SelectCellDefinition
                {
                    ItemsSource = values
                };
            }

            if (pd.ItemsSourceProperty != null || pd.ItemsSource != null)
            {
                return new SelectCellDefinition
                {
                    ItemsSource = pd.ItemsSource,
                    ItemsSourceProperty = pd.ItemsSourceProperty
                };
            }

            return new TextCellDefinition();
        }
        /// <summary>
        /// Inserts item to <see cref="DataGrid" />.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="index">The index.</param>
        /// <returns>
        ///   <c>true</c> if insertion is successful, <c>false</c> otherwise.
        /// </returns>
        public override bool InsertItem(DataGrid owner,  int index)
        {
            var list = owner.ItemsSource;
            if (list == null)
            {
                return false;
            }

            var itemType = TypeHelper.GetItemType(list);

            object newItem = null;
            if (itemType == typeof(string))
            {
                newItem = string.Empty;
            }

            if (itemType == typeof(double))
            {
                newItem = 0.0;
            }

            if (itemType == typeof(int))
            {
                newItem = 0;
            }

            try
            {
                if (newItem == null)
                {
                    newItem = owner.CreateInstance(itemType);
                }
            }
            catch
            {
                return false;
            }

            if (index < 0)
            {
                list.Add(newItem);
            }
            else
            {
                list.Insert(index, newItem);
            }

            return true;
        }
        /// <summary>
        /// Gets the item in cell.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell reference.</param>
        /// <returns>
        /// The item <see cref="object" />.
        /// </returns>
        public override object GetItem(DataGrid owner, CellRef cell)
        {
            var list = owner.ItemsSource;
            if (list == null)
            {
                return null;
            }

            var index = this.GetItemIndex(owner, cell);
            if (index >= 0 && index < list.Count)
            {
                return list[index];
            }

            return null;
        }
        /// <summary>
        /// Gets the item in cell.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell reference.</param>
        /// <returns>
        /// The <see cref="object" />.
        /// </returns>
        public override object GetItem(DataGrid owner,  CellRef cell)
        {
            var list = owner.ItemsSource;
            var rowIndex = cell.Row;
            var columnIndex = cell.Column;
            if (list == null || rowIndex < 0 || columnIndex < 0)
            {
                return null;
            }

            if (rowIndex >= list.Count)
            {
                return null;
            }

            var row = list[rowIndex] as IList;
            if (row == null || columnIndex >= row.Count)
            {
                return null;
            }

            return ((IList)list[rowIndex])[columnIndex];
        }
        /// <summary>
        /// Applies the properties to the specified cell definition.
        /// </summary>
        /// <param name="cd">The cell definition.</param>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell.</param>
        /// <param name="pd">The row/column definition.</param>
        /// <param name="item">The current value of the cell.</param>
        protected virtual void ApplyProperties(CellDefinition cd, DataGrid owner, CellRef cell, PropertyDefinition pd, object item)
        {
            cd.HorizontalAlignment = pd.HorizontalAlignment;
            cd.BindingPath = pd.PropertyName ?? owner.Operator.GetBindingPath(owner, cell);
            cd.IsReadOnly = pd.IsReadOnly;
            cd.FormatString = pd.FormatString;
            if (pd.Converter != null)
            {
                cd.Converter = pd.Converter;
            }

            cd.ConverterParameter = pd.ConverterParameter;
            cd.ConverterCulture = pd.ConverterCulture;

            cd.IsEnabledBindingParameter = pd.IsEnabledByValue;
            cd.IsEnabledBindingPath = pd.IsEnabledByProperty;
            cd.BackgroundBindingPath = pd.BackgroundProperty;

            if (pd.Background != null)
            {
                cd.BackgroundBindingSource = pd.Background;
                cd.BackgroundBindingPath = string.Empty;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DataGridOperator" /> class.
 /// </summary>
 /// <param name="owner">The owner or this operator.</param>
 protected DataGridOperator(DataGrid owner)
 {
     this.Owner = owner;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ListListOperator" /> class.
 /// </summary>
 /// <param name="owner">The owner.</param>
 public ListListOperator(DataGrid owner)
     : base(owner)
 {
 }
 /// <summary>
 /// Gets the binding path for the specified cell.
 /// </summary>
 /// <param name="owner">The owner.</param>
 /// <param name="cell">The cell.</param>
 /// <returns>
 /// The binding path
 /// </returns>
 public override string GetBindingPath(DataGrid owner, CellRef cell)
 {
     return $"[{cell.Row}][{cell.Column}]";
 }
        /// <summary>
        /// Sets value to item in cell.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell reference.</param>
        /// <param name="value">The value.</param>
        public override void SetValue(DataGrid owner, CellRef cell, object value)
        {
            var list = owner.ItemsSource;
            if (list == null || cell.Row < 0 || cell.Column < 0 || cell.Row >= list.Count)
            {
                return;
            }

            var row = list[cell.Row] as IList;
            if (row == null || cell.Column >= row.Count)
            {
                return;
            }

            row[cell.Column] = value;
        }
 /// <summary>
 /// Gets the binding path for the specified cell.
 /// </summary>
 /// <param name="owner">The owner.</param>
 /// <param name="cell">The cell.</param>
 /// <returns>
 /// The binding path
 /// </returns>
 public override string GetBindingPath(DataGrid owner, CellRef cell)
 {
     var index = this.GetItemIndex(owner, cell);
     return $"[{index}]";
 }
        /// <summary>
        /// Gets the item index for the specified cell.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell.</param>
        /// <returns>
        /// The get item index.
        /// </returns>
        protected virtual int GetItemIndex(DataGrid owner, CellRef cell)
        {
            if (owner.WrapItems)
            {
                return owner.ItemsInRows ? (cell.Row * owner.Columns) + cell.Column : (cell.Column * owner.Rows) + cell.Row;
            }

            return owner.ItemsInRows ? cell.Row : cell.Column;
        }
        /// <summary>
        /// Sets value to item in cell.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="cell">The cell reference.</param>
        /// <param name="value">The value.</param>
        public override void SetValue(DataGrid owner, CellRef cell, object value)
        {
            var list = owner.ItemsSource;
            if (list == null || cell.Column < 0 || cell.Row < 0)
            {
                return;
            }

            var index = this.GetItemIndex(owner, cell);
            list[index] = value;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ListListOperator" /> class.
 /// </summary>
 /// <param name="owner">The owner.</param>
 public ListListOperator(DataGrid owner)
     : base(owner)
 {
 }