protected override int IssueQuery(string search, string group, 
            int pageIndex, int pageSize)
        {
            search = (search != null) ? search.Trim() : null;

            //проверка, что строка запроса не пуста
            if (string.IsNullOrEmpty(search))
            {
                PickerDialog.ErrorMessage = "Введите подстроку для поиска";
                return 0;
            }

            //получить данные, удовлетворяющие запросу
            var dm = new DataManager(EditorControl.PickerData.ConnectionString, EditorControl.PickerData.QueryString);
            DataTable table = null;
            SPSecurity.RunWithElevatedPrivileges(() => table = dm.GetRecords(search));

            //запрошенные данные не найдены
            if (table.Rows.Count == 0)
            {
                PickerDialog.ErrorMessage = "По Вашему запросу ничего не найдено";
                return 0;
            }

            // Return results to dialog
            PickerDialog.Results = table;
            PickerDialog.ResultControl.PageSize = table.Rows.Count;

            // Return number of records
            return table.Rows.Count;
        }
        /// <summary>
        /// �������� ��������. ������ ��� ������ �� ������ ��������� �����
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public override PickerEntity ValidateEntity(PickerEntity entity)
        {
            if (entity.IsResolved)
                return entity;

            var dm = new DataManager(PickerData.ConnectionString, PickerData.QueryString);
            DataRow row = null;
            SPSecurity.RunWithElevatedPrivileges(() => row = dm.GetRecord(entity.DisplayText));

            if (row == null)
                return entity;

            // Resolve entity
            var pe = new PickerEntity
                         {
                             Key = row["ID"].ToString(),
                             DisplayText = row["Value"].ToString()
                         };
            entity = pe;
            entity.IsResolved = true;

            ////���� �� ��������
            //if (entity.DisplayText.Contains(CustomExternalLookupValue.Separator))
            //    ErrorMessage = string.Format("��������������: �������� �������� ������������ ��� ������� ���������� ������� {0} � ����� ��������� ���������. ���������� �������� �������� �� ������� ��������� ������", CustomExternalLookupValue.Separator);

            return entity;
        }
        //заполнение компонентов вариантами для выбора или настройка для связи с источником данных
        protected override void OnLoad(EventArgs e)
        {
            EnsureChildControls();

            if (ControlMode == SPControlMode.Display)
                return;

            if (_pickerEntityMode)
            {
                //настройка свойств EntityPicker'а для подключения к внешнему источнику данных
                var editorData = new CustomExternalLookupData
                                     {
                                         ConnectionString = _connString,
                                         QueryString = string.IsNullOrEmpty(QueryString) ? _queryString : QueryString
                                     };

                _entityEditor.PickerData = editorData;
                _entityEditor.Enabled = ExecuteQuery;
            }
            else
            {
                if (ExecuteQuery)
                {
                    if (!Page.IsPostBack || _queryStringChanged)
                    {
                        var dm = new DataManager(_connString, string.IsNullOrEmpty(QueryString) ? _queryString : QueryString);
                        DataTable records = null;
                        SPSecurity.RunWithElevatedPrivileges(() => records = dm.GetRecords());

                        if (MultiSelectMode)
                        {
                            _leftListBox.Items.Clear();

                            foreach (DataRow rec in records.Rows)
                            {
                                var newListItem = new ListItem
                                                      {Value = rec["ID"].ToString(), Text = rec["Value"].ToString()};
                                _leftListBox.Items.Add(newListItem);
                            }

                            _leftListBox.Enabled = _rightListBox.Enabled = true;
                        }
                        else
                        {
                            _dropDownList.Items.Clear();
                            foreach (DataRow row in records.Rows)
                                _dropDownList.Items.Add(new ListItem(row["Value"].ToString(), row["ID"].ToString()));
                            if (!Field.Required)
                                _dropDownList.Items.Insert(0, new ListItem("(нет)", string.Empty));
                            _dropDownList.Enabled = true;
                        }
                    }
                }
                else
                {
                    if (MultiSelectMode)
                    {
                        _leftListBox.Items.Clear();
                        _rightListBox.Items.Clear();
                        _rightListBoxValues.Value = "";
                        _leftListBox.Enabled = _rightListBox.Enabled = false;
                    }
                    else
                    {
                        _dropDownList.Items.Clear();
                        _dropDownList.Enabled = false;
                    }
                }
            }

            if (MultiSelectMode && !_pickerEntityMode)
            {
                //проверка того, что в поле множественного выбора выбраны только допустимые значения
                string[] valuesSplit = _rightListBoxValues.Value.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
                if (valuesSplit.Any(val => _leftListBox.Items.FindByValue(val) == null))
                    throw new SPException("Выбрано недопустимое значение");

                //обновление атрибутов title для options select'а
                AddTitlesToListBoxItems(_leftListBox.Items);
            }

            base.OnLoad(e);
        }
        /// <summary>
        /// ������� ��������� �������� �������� ��� ������ �� ��������, ������� �� ������� ���������
        /// </summary>
        /// <param name="unresolvedText"></param>
        /// <returns></returns>
        protected override PickerEntity[] ResolveErrorBySearch(string unresolvedText)
        {
            base.ResolveErrorBySearch(unresolvedText);

            var dm = new DataManager(PickerData.ConnectionString, PickerData.QueryString);
            DataTable results = null;
            SPSecurity.RunWithElevatedPrivileges(() => results = dm.GetRecords(unresolvedText));

            return ConvertDataTableToPickerEntities(results);
        }
        protected void UpdateButton_Click(object sender, EventArgs e)
        {
            string connString = _field.GetCustomProperty("ConnectionString").ToString();
            string queryString = _field.GetCustomProperty("QueryString").ToString();

            SharedModule.CheckConnectionProperties(_field.Title, connString, queryString);

            var dm = new DataManager(connString, queryString);
            DataTable data = null;
            SPSecurity.RunWithElevatedPrivileges(() => data = dm.GetRecords());

            int changedCount = 0;
            var deletedFromBDMessages = new List<string>();

            bool textChanged = false;
            foreach (SPListItem item in _list.Items)
            {
                if (item[_field.Id] == null || item[_field.InternalName + "ID"] == null || item[_field.InternalName + "ID"].ToString() == "")
                    continue;

                string resultText = "";

                if (_field.TypeAsString == "CustomExternalLookup")
                {
                    string value = item[_field.InternalName + "ID"].ToString();
                    string text = item[_field.Id].ToString();

                    DataRow row = data.Rows.Find(Convert.ToInt32(value));
                    if (row != null)
                    {
                        if (row["Value"].ToString() != text)
                        {
                            text = row["Value"].ToString();
                            textChanged = true;
                            ++changedCount;
                        }
                    }
                    else
                        deletedFromBDMessages.Add(string.Format("<a href=\"{0}\" target=\"_blank\">{1}</a>: {2}", SPHttpUtility.UrlPathEncode(_web.Site.MakeFullUrl(_list.DefaultDisplayFormUrl + "?ID=" + item.ID.ToString()), false), item.Title, text));

                    resultText = text;
                }
                else if (_field.TypeAsString == "CustomExternalLookupMulti")
                {
                    var mcValues = new SPFieldMultiColumnValue(item[_field.InternalName + "ID"].ToString());
                    var mcTexts = new SPFieldMultiColumnValue(item[_field.Id].ToString());

                    for (int i = 0; i < mcValues.Count; ++i)
                    {
                        DataRow row = data.Rows.Find(Convert.ToInt32(mcValues[i]));
                        if (row != null)
                        {
                            if (row["Value"].ToString() != mcTexts[i])
                            {
                                mcTexts[i] = row["Value"].ToString();
                                textChanged = true;
                                ++changedCount;
                            }
                        }
                        else
                            deletedFromBDMessages.Add(string.Format("<a href=\"{0}\" target=\"_blank\">{1}</a>: {2}", SPHttpUtility.UrlPathEncode(_web.Site.MakeFullUrl(_list.DefaultDisplayFormUrl + "?ID=" + item.ID.ToString()), false), item.Title, mcTexts[i]));

                    }
                    resultText = mcTexts.ToString();
                }

                if (textChanged)
                {
                    item[_field.Id] = resultText;
                    item.Update();
                }
            }

            ResultLiteral.Text = string.Format("Обновлено значений: {0}. Значений, ссылающихся на удалённые данные: {1}", changedCount, deletedFromBDMessages.Count);

            if (deletedFromBDMessages.Count > 0)
            {
                ResultLiteral.Text = ResultLiteral.Text + "<br/><br/>Ссылаются на удалённые данные:<br/>";
                foreach (string val in deletedFromBDMessages)
                    ResultLiteral.Text = ResultLiteral.Text + string.Format("{0}<br/>", val);
            }

            CancelButton.Text = "Закрыть";
        }