Правильное связывание данных со списком и обработка его событий - PullRequest
5 голосов
/ 07 мая 2010

У меня есть таблица в SQL Server, которая выглядит следующим образом:

ID Code Name     Surname
1   MS  Mike     Smith 
2   JD  John     Doe
3   UP  Unknown  Person

и так далее ...

Теперь я хочу связать данные из этой таблицы в ComboBox вспособ, которым в ComboBox я отображал значение из столбца Код.

Я делаю привязку следующим образом:

SqlDataAdapter sqlAdapter = new SqlDataAdapter("SELECT * FROM dbo.Users ORDER BY Code", MainConnection);
sqlAdapter.Fill(dsUsers, "Users");
cbxUsers.DataSource = dsUsers.Tables["Users"];
cmUsers = (CurrencyManager)cbxUsers.BindingContext[dsUsers.Tables["Users"]];
cbxUsers.DisplayMember = "Code";

И этот код, кажется, работает.Я могу прокрутить список кодов.Также я могу начать писать код вручную, и ComboBox автоматически заполняет код для меня.

Однако я хотел поставить метку в верхней части списка, чтобы отобразить имя и фамилию выбранного в данный момент кода пользователя.

Моя строка слова была такой: «Итак, мне нужно найти событие, которое сработает после изменения кода в выпадающем списке, и в этом случае я получу текущий DataRow ...»

Я просматривал события выпадающего списка, перепробовал многие из них, но безуспешно.

Например:

private void cbxUsers_SelectionChangeCommitted(object sender, EventArgs e)
{
 if (cmUsers != null)
 {
  DataRowView drvCurrentRowView = (DataRowView)cmUsers.Current;
  DataRow drCurrentRow = drvCurrentRowView.Row;
  lblNameSurname.Text = Convert.ToString(drCurrentRow["Name"]) + " " + Convert.ToString(drCurrentRow["Surname"]);
 }
}

Это дает мне странные результаты.Во-первых, когда я прокручиваю с помощью мыши, он не возвращает строку, которую я ожидаю получить.Например, на JD он показывает мне «Mike Smith», на MS - «John Doe», а на UP снова показывает «Mike Smith»!Другая проблема заключается в том, что когда я начинаю набирать в ComboBox и нажимаю ввод, это не вызывает событие.

Однако все работает, как и ожидалось, когда я связываю данные с lblNameSurname.Text следующим образом:

lblNameSurname.DataBindings.Add("Text", dsusers.Tables["Users"], "Name");

Проблема в том, что я могу связать только один столбец, и я хочу иметь два.Я не хочу использовать два ярлыка для этого (один для отображения имени, а другой для отображения фамилии).

Итак, каково решение моей проблемы?

Кроме того, у меня есть одинВопрос, связанный с выбором данных в ComboBox.Теперь, когда я набираю что-то в поле со списком, это позволяет мне печатать буквы, которых нет в списке.Например, я начинаю набирать «J» и вместо окончания «D», чтобы у меня было «JD», я набираю «Jsomerandomtexthere».Combobox позволит это, но такого элемента нет в списке.Другими словами, я хочу, чтобы выпадающий список не позволял пользователю вводить код, которого нет в списке кодов.

Ответы [ 5 ]

2 голосов
/ 15 июля 2010

Я только что проверил это, и я думаю, что то, что вы ищете, связано с неправильным событием (возможно, даже с неправильным объектом).

Я только что попытался добавить событие в обработчик PositionChanged объекта CurrencyManager (cmUsers), и оно работало точно так, как предполагалось. Единственная проблема, с которой я столкнулся, это то, что при первой загрузке он не попадает в PositionChanged, поэтому первый элемент никогда не привязывается к метке (я уверен, что есть более легкое исправление). http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingmanagerbase.positionchanged.aspx

Выполнил небольшой тест, чтобы увидеть, какое событие было запущено первым, и кажется, что событие SelectionChangeCommitted сработало до PositionChanged, то есть CurrencyManager еще не обновил свою внутреннюю позицию, поэтому строка:

DataRowView drvCurrentRowView = (DataRowView)cmUsers.Current;

Тянет неправильный DataRow.

Забыл о вашем втором выпуске. Большинство элементов управления не обрабатывают нажатия клавиш, поэтому вам нужно привязать события OnKeyDown или OnKeyPress для запуска любой функции, которую вы хотите (найти индекс, связанный с типизированным объектом [т.е. FindString ()], и установить для свойства ComboBox.SelectedIndex значение найденный индекс, иначе выведите предупреждение). Например:

if(e.KeyCode == Keys.Enter)
{
    int indx;
    cmbBox.SelectAll();
    if((indx = FindString(cmbBox.SelectedText)) != -1)
        cmbBox.SelectedIndex = indx;
    else
        // Some warning
}

Редактировать Прочитав ваши комментарии, я нашел более простой способ сделать проверку. В событии «KeyPress» ComboBox используйте следующий код:

if(e.KeyChar != (char)Keys.Enter)
{
    if(cmbBox.FindString(cmbBox.Text + e.KeyChar) == -1)
    {
        e.Handled= true;
    }
}

Без суеты, без суеты. Поскольку здесь мы ограничиваемся только элементами в списке, нам не нужно обрабатывать их, когда они нажимают Enter, поскольку это должно автоматически изменять выбранный элемент (однако, не мешало бы выполнить некоторую проверку, чтобы убедиться, что это правильно cAsE, или просто изменили свойство SelectedIndex вручную при нажатии клавиши Enter). Тем не менее, надеюсь, что это помогло кому-то.

0 голосов
/ 08 июля 2010

Обычно событие изменения выбранного индекса выпадающего списка происходит, когда вы меняете свой выбор и перемещаете фокус за пределы раскрывающегося списка, как щелчок снаружи или нажатие клавиши табуляции ...

Если вам нужно немедленно запустить его, вам нужно искать другое событие или вызывать событие через Событие JavaScript onchange и т. Д. *

0 голосов
/ 09 мая 2010

Хорошо, вы можете изменить свой SQL, чтобы получить имя и фамилию в виде одного столбца, а затем привязать один раз к этому столбцу. Кроме того, я бы поместил комбо и метку на панель обновления Ajax.

Относительно проверки: для проверки на клиенте вам необходимо заранее иметь все возможные значения на клиенте или выполнить обратную передачу для каждого символа и нажать SQL (что, вероятно, не очень хорошая идея - убивает сервер): *

SELECT code FROM TABLE WHERE code LIKE @x + '%' 

Является ли автозаполнение приемлемым вариантом? Взгляните, например, на jQuery autocompletebox.

0 голосов
/ 07 июля 2010

Попробуйте следующее:

Создайте объект Binding вручную, чтобы у вас была ссылка на него. Используйте объект Binding для привязки к свойству SelectedItem вашего ComboBox. Я думаю, что это должно получить вам выбранный DataRow. Добавьте этот объект Binding в коллекцию DataBindings метки.

Обработайте событие Binding.Format (или это может быть Parse - не совсем помню, какое событие применяется при привязке в каком направлении) и используйте объект DataRow, полученный в объекте args события, для формирования соответствующей строки имени, содержащей оба имя и фамилия. Вам нужно установить какое-то другое свойство EventArgs для этой строки.

Возможно, вам также придется поиграть со свойством FormattingEnabled класса Binding - с тех пор, как я это делал в последний раз, прошло немало времени, я просто помню, что это было немного сложно.

См. Документацию для событий Parse и Format: http://msdn.microsoft.com/en-us/library/system.windows.forms.binding_events.aspx

0 голосов
/ 07 мая 2010

Что касается вашего второго вопроса, я обычно делаю два способа: либо обработать событие Validating для поля со списком, прежде чем покинуть форму (и отключить кнопку продолжения или вызвать сообщение об ошибке) или установите ComboBox.DropDownStyle на ComboBoxStyle.DropDownList

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...