public static void SetECTableDataBinding(this DataGridView _dgv, ECTable _table,
                                                 FieldFilter _ff,
                                                 params string[] _fields)
        {
            if (_dgv.Tag == null)
            {
                _dgv.Tag = Guid.NewGuid().ToString();
            }
            else if (!dataGridViewsWithECTableBinding.ContainsKey(_dgv.Tag.ToString()))
            {
                throw new ECDataGridTagPropertyInUse(_dgv);
            }

            string key            = $"{_dgv.Tag};{_table.TableName}";
            string mappingColName = $"{ _table.TableName };{mappingColNameConst}";

            if (dataGridViewsWithECTableBinding.ContainsKey(key))
            {
                throw new ECBindingAlreadyExistsException(_dgv);
            }
            dataGridViewsWithECTableBinding.Add(key, _table);
            _dgv.AddDataFromECTable(_table, _ff, true, _fields);

            _table.OnBeforeFindSet += delegate(object sender, ECTable _callerTable)
            {
                _dgv.Rows.Clear();
                _dgv.Columns.Clear();
                _dgv.Refresh();
            };

            _table.OnAfterFindSet += delegate(object sender, ECTable _callerTable)
            {
                _dgv.AddDataFromECTable(_callerTable, _ff, true, _fields);
            };

            _table.OnAfterModify += delegate(object sender, ECTable _callerTable)
            {
                foreach (PropertyInfo p in _table.GetType().GetProperties().Where(x => x.IsDefined(typeof(ECTableFieldAttribute))))
                {
                    string            colName          = $"{ _callerTable.TableName };{p.Name}";
                    string            value            = p.GetValue(_callerTable).ToString();
                    int               currentBufferIdx = _table.GetCurentBufferIndex();
                    DataGridViewRow[] rows             = new DataGridViewRow[_dgv.Rows.Count];
                    _dgv.Rows.CopyTo(rows, 0);

                    DataGridViewRow row = rows.First(x => (int)x.Cells[mappingColName].Value == currentBufferIdx);

                    row.Cells[colName].Value = value;
                }
            };

            _dgv.CellEnter += delegate(object sender, DataGridViewCellEventArgs e)
            {
                _dgv.Rows[e.RowIndex].Selected = _dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
                if ((!_dgv.AllowUserToAddRows) || (_dgv.AllowUserToAddRows && e.RowIndex < _dgv.Rows.Count - 1))
                {
                    _table.SetCurentBufferIndex(Convert.ToInt32(_dgv.Rows[e.RowIndex].Cells[mappingColName].Value));
                }
            };

            _dgv.CellEndEdit += delegate(object sender, DataGridViewCellEventArgs e)
            {
                PropertyInfo p;
                string       colName   = _dgv.Columns[e.ColumnIndex].Name;
                string       fieldName = colName.Substring(colName.IndexOf(';') + 1);

                //_table.SetCurrentBufferIndex(Convert.ToInt32(_dgv.Rows[e.RowIndex].Cells[mappingColName].Value));
                p = _table.GetType().GetProperty(fieldName);
                Object valueString = _dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
                if (valueString == null)
                {
                    valueString = "";
                }

                Object valueWithCorrectType = Convert.ChangeType(valueString, p.GetValue(_table).GetType());
                p.SetValue(_table, valueWithCorrectType);
            };

            _dgv.Disposed += delegate(object sender, EventArgs a)
            {
                dataGridViewsWithECTableBinding.Remove(_dgv.Tag.ToString());
            };
        }