Используете пустую строку по умолчанию в ComboBox со стилем "DropDownList"? - PullRequest
0 голосов
/ 26 марта 2010

Я пытаюсь написать метод, который принимает ComboBox, DataTable и TextBox в качестве аргументов. Цель этого - отфильтровать элементы, отображаемые в ComboBox, в соответствии с TextBox.Text. DataTable содержит полный список возможных записей, которые затем будут отфильтрованы. Для фильтрации я создаю DataView для DataTable, добавляю RowFilter и затем связываю это представление с ComboBox как DataSource.

Чтобы пользователь не мог вводить в ComboBox, я выбираю DropDownStyle DropDownList. Пока это работает нормально, за исключением того, что пользователь также должен иметь возможность выбирать ничего / пустую строку. Фактически, это должен быть элемент по умолчанию, который будет отображаться (чтобы избежать случайного выбора неправильного элемента, если пользователь слишком быстро щелкает по диалоговому окну).

Я попытался решить эту проблему, добавив новую строку в представление. Хотя в некоторых случаях это работает, основная проблема заключается в том, что любой метод DataTable может быть передан методу. Если DataTable содержит столбцы, которые не могут быть нулевыми и не содержат значения по умолчанию, я полагаю, что возникнет ошибка, добавив пустую строку.

Можно создать представление, содержащее только столбец, определенный как DisplayMember, и столбец, определенный как ValueMember. Увы, этого нельзя сделать с помощью представления в C #. Я хотел бы избежать создания истинной копии DataTable любой ценой, так как кто знает, насколько большой он станет со временем.

У вас есть предложения, как обойти эту проблему?

Вместо представления, могу ли я создать объект, содержащий два элемента, и назначить DisplayMember и ValueMember этим элементам? Будут ли участники переданы в качестве ссылки (что я надеюсь) или будет создано истинное копирование (в этом случае это не будет решением)?

Большое спасибо за помощь!

С наилучшими пожеланиями

public static void ComboFilter(ComboBox cb, DataTable dtSource, TextBox filterTextBox)
{
 cb.DropDownStyle = ComboBoxStyle.DropDownList;
 string displayMember = cb.DisplayMember;
 DataView filterView = new DataView(dtSource);
 filterView.AddNew();
 filterView.RowFilter = displayMember + " LIKE '%" + filterTextBox.Text + "%'";
 cb.DataSource = filterView;
}

1 Ответ

0 голосов
/ 27 марта 2010

Хорошо, случайно я наткнулся на рабочее решение: любые изменения в DataView, такие как добавление новой строки, должны быть завершены с использованием .EndEdit. Если вы этого не сделаете, вы столкнетесь с побочными эффектами, такими как добавленная строка не сортируется должным образом. НО: не добавляя .EndEdit, вы также получите преимущество: C # не будет проверять, если какой-либо из столбцов в базовом DataTable (dtSource) не допускает нулевое значение!

Итак, в качестве решения я добавил .EndEdit в try-Block. Если DataTable допускает пустое значение для каждого столбца, он будет работать, и пустая строка появится в верхней части списка. Если он не допускает null, EndEdit не будет выполнен, однако пустая строка все равно будет добавлена ​​в нижней части ComboBox.

Обратите внимание, что если вы установили автоинкремент в dtSource, пустая строка также будет возвращать SelectedValue (скорее всего, -1). Это необходимо учитывать при использовании этого метода!

Ура!

public static void ComboFilter(ComboBox cb, DataTable dtSource, TextBox filterTextBox)
{
    cb.DropDownStyle = ComboBoxStyle.DropDownList;
    string displayMember = cb.DisplayMember;
    DataView filterView = new DataView(dtSource);
    DataRowView newRow = filterView.AddNew();
    newRow[displayMember] = "";
    try { newRow.EndEdit(); }   // fails, if a column in dtSource does not allow null
    catch (Exception) { }       // works, but the empty line will appear at the end
    filterView.RowFilter = displayMember + " LIKE '%" + filterTextBox.Text + "%'";
    filterView.Sort = displayMember;
    cb.DataSource = filterView;
}
...