Вставить строку в список в нужное место
Одна запись в списке соответствует 1 записи массива. То есть в списке название элемента, а в массиве описание элемента. При нажатии на название элемента в списке в тестовом поле появляется описание. Определение описания происходит по индексу.... т.е. происходит щелчок по элементу списка - SelectIndexChange - в текстовое поле копируем описание с номером щелкнутого элемента из массива . Номер элемента соответствует номеру описания
Допустим в списке следующее:
элемент 2
элемент 3
элемент 4
То в массиве описания:
Описание элемента 2
Описание элемента 3
Описание элемента 4
и если пользователь выделил "Элемент 3"( он по счету 2 начиная с 0), то показывается описание из массива по счету 2.
А вот сама проблема: необходимо позволить пользователю добавлять элементы. но необходимо сохранить расположение элементов по алфавиту. Сортировать через Sort() нельзя, поскольку необходимо сохранить зависимость: "номер элемента - номер описания". Рассмотрим конкетный пример, в списке имеется:
E-1100
E-1200
....
E-1500
Необходимо добавить элемент E-1105 и E-12000 и при этом сохранить нашу зависимость.Описание новых элементов тоже имеется, но нам не важно какое оно сейчас.
Я в своей программе начинаю перебирать в цикле все элементы и списка и сравнивать их с новым элементом:
где LBAdds.Items(i)- очередной элемент
а RTBAdds.Text - новый элемент
т.е. я пользуюсь функцией сравнения строк <.
все работает, но не так.
E-1105 добавится по алфавиту норм, а E-12000 добавится не в конец (как по логике), а после E-1200. Это вилимо происходит потому что н сравнивает поочередно посимвольно и считает, что 2 на втором месте в новом элементе меньше чем 5 последнем элементе, а не сравнивает все целеком. Новый элемент необязательно начинается с "E-" и может состоять как из цифр, так и из букв, а также и из тех и из других.
Помогите разработать эффективный алгоритм добавления нового элемента по алфавиту. Заранее огромное спс.
Отказаться от этого.
ListBox вполне способен отображать "неважно-какие-объекты".
Для эффективного решения задачи требуется научиться пользоваться:
1) классом System.Collections.Generic.List<T>.
2) компонентом BindingSource
Кладем на форму компонент ListBox (назовем его box), кладем BindingSource (назовем box_source). Свойству DataSource листбокса назначаем box_source. Для отображения описания текущего элемента кладем TextBox (называем txt_description). Больше ничего с формой не делаем.
В коде объявляем класс вида:
public MyItem(string name, string description) {
this._name = name;
this._description = description;
}
private string _name;
public string Name {
get {
return _name;
}
}
private string _description;
public string Description {
get {
return _description;
}
}
}
Код формы выглядит так:
public Form1() {
InitializeComponent();
// txt_description будет автоматически привязываться к текущему выделенному объекту
txt_description.DataBindings.Add(new Binding("Text", box_source, "Description"));
_items.Add(new MyItem("item 1", "Hello"));
_items.Add(new MyItem("item 2", "World"));
_items.Add(new MyItem("item 3", "!"));
BindBoxItems();
}
private List<MyItem> _items = new List<MyItem>();
private void BindBoxItems() {
int old_selected_index = box.SelectedIndex;
box_source.DataSource = null;
box_source.DataSource = _items;
if (_items.Count > 0) {
box.DisplayMember = "Name";
if (old_selected_index < _items.Count) {
// сохраняем предыдущую позицию выделения
box.SelectedIndex = old_selected_index;
}
}
}
}
После каждого изменения списка _items (добавление, удаление, сортировка) нужно вызывать метод BindBoxItem.
Так вот.... у теб все прекрасно в коде. Одно не понял....
Добавили в список новые элементы:
_items.Add(new MyItem("item 2", "World"));
_items.Add(new MyItem("item 3", "!"));
Потом в процедуре указываем источник Box_source:
У ListBox указываем какое поле класса отображать:
А где заполнение ListBox, или связка его с items, чтобы он автоматически отображал элементы items.... Т.е. как и где ListBox узнает о изменении коллекции _items? Т.е.2, как в ListBox попадают элементы?
txt_description.DataBindings.Add(new Binding("Text", box_source, "Description"));
Все догнал с этим кодом, который выше, кроме: Мы добавили связующее поле "Description"... А где и как он узнает, что именно по SelectedIndex нужно это делать? Можешь прокомментировать код и для чайников... хотя я вроде все понимаю кроме этих моментов.
И попрошу без отправки в MSDN ибо был там и раздела "Cods by hardcase" увы там нет... и еще... ты пишешь на C(++,# я незнаю, ибо с ними не работал и неразличаю), а мне надо на VB.Net, я обычно легко переводил твой код, но с:
this._name = name;
this._description = description;
}
не смог... это же конструктор? я не смог найти в MSDN как сними работать, а именно: параметры:string name, string description по идее нужно мне написать:
Me._name = name [COLOR="Green"]' Ну или что то вместо Me[/COLOR]
Me._description = description
End Что-то(?)
Но он ругается на параметры, просит массив с границей 0 и испоьзовать "To". Помоги пожалуйста
P.S. Я конечно понимаю, что тебе проще создать свой алгоритм, который в 1000 проще и мощней (не спорю), но мне же всю свою прогу переделывать... Может ты мой алгоритм доделать поможешь?
Так вот.... у теб все прекрасно в коде. Одно не понял....
Добавили в список новые элементы:
_items.Add(new MyItem("item 2", "World"));
_items.Add(new MyItem("item 3", "!"));
ListBox тягает элементы из BindingSource-а, а тот - из коллекции _items. У box и у box_source есть свойство DataSource, только box-у мы в дизайнере назначили box.DataSource = box_source. А потом в коде (метод BindBoxItems) мы при каждой модификации коллекции _items назначаем box_source.DataSource = _items (с предварительным обнулением).
txt_description.DataBindings.Add(new Binding("Text", box_source, "Description"));
txt_description не лезет по SelectedIndex в листбокс box. Он лезет по свойству Current у биндинг сурса box_source. Лист бокс всегда будет изменять это свойство у box_source при выделении элементов.
this._name = name;
this._description = description;
}
Да, это конструктор. И объявлять его нужно по правилам VB.NET. Проблема в том, что я вот так сходу не пишу на VB.NET - мне быстрее написать на C# или Nemerle. ;)
Public Sub New(ByVal name As String, ByVal description As String)
Me._name = name
Me._description = description
End Sub
Private _name As String
Public ReadOnly Property Name() As String
Get
Return _name
End Get
End Property
Private _description As String
Public ReadOnly Property Description() As String
Get
Return _description
End Get
End Property
End Class
public MyItem(string name, string description) {
this._name = name;
this._description = description;
}
private string _name;
public string Name {
get {
return _name;
}
}
private string _description;
public string Description {
get {
return _description;
}
}
public override string ToString()
{
return this.Name;
}
}
MyItem item = new MyItem("Name", "Description");
listBox.Items.Add(item);
// Тянем обратно
item = listBox.Items[0] as MyItem;
Такой вариант хорош, если сортировка - часть представления и не играет роли в бизнес-логике.
Кстати да :D
Я сам уже давно привык к биндингам, и по-тупому делать разучился.
Даже если нельзя в том виде, в котором приведены примеры, научить классы сравнивать себя друг с другом несложно.
Для примера hardcase:
public MyItem(string name, string description) {
this._name = name;
this._description = description;
}
private string _name;
public string Name {
get {
return _name;
}
}
private string _description;
public string Description {
get {
return _description;
}
}
// Реализуем IComparable
public int CompareTo(MyItem other)
{
return Name.CompareTo(other.Name);
}
}
// Теперь можем сортировать
_items.Sort();
Да. Current свойство будет соответствовать первому элементу в выделении.