Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вставить строку в список в нужное место

1.8K
09 января 2009 года
NextTime
217 / / 19.12.2007
Пишу Программу на Vb.Net 2008... Имеется список ListBox.... Там уже все по алфавиту и имеется List(of string), т.е. массив.
Одна запись в списке соответствует 1 записи массива. То есть в списке название элемента, а в массиве описание элемента. При нажатии на название элемента в списке в тестовом поле появляется описание. Определение описания происходит по индексу.... т.е. происходит щелчок по элементу списка - SelectIndexChange - в текстовое поле копируем описание с номером щелкнутого элемента из массива . Номер элемента соответствует номеру описания
Допустим в списке следующее:
 
Код:
элемент 1
элемент 2
элемент 3
элемент 4

То в массиве описания:
 
Код:
Описание элемента 1
Описание элемента 2
Описание элемента 3
Описание элемента 4

и если пользователь выделил "Элемент 3"( он по счету 2 начиная с 0), то показывается описание из массива по счету 2.
А вот сама проблема: необходимо позволить пользователю добавлять элементы. но необходимо сохранить расположение элементов по алфавиту. Сортировать через Sort() нельзя, поскольку необходимо сохранить зависимость: "номер элемента - номер описания". Рассмотрим конкетный пример, в списке имеется:
 
Код:
E-1000
E-1100
E-1200
....
E-1500

Необходимо добавить элемент E-1105 и E-12000 и при этом сохранить нашу зависимость.Описание новых элементов тоже имеется, но нам не важно какое оно сейчас.
Я в своей программе начинаю перебирать в цикле все элементы и списка и сравнивать их с новым элементом:
 
Код:
If LBAdds.Items(i) < RTBAdds.Text Then Exit Do

где LBAdds.Items(i)- очередной элемент
а RTBAdds.Text - новый элемент
т.е. я пользуюсь функцией сравнения строк <.
все работает, но не так.
E-1105 добавится по алфавиту норм, а E-12000 добавится не в конец (как по логике), а после E-1200. Это вилимо происходит потому что н сравнивает поочередно посимвольно и считает, что 2 на втором месте в новом элементе меньше чем 5 последнем элементе, а не сравнивает все целеком. Новый элемент необязательно начинается с "E-" и может состоять как из цифр, так и из букв, а также и из тех и из других.
Помогите разработать эффективный алгоритм добавления нового элемента по алфавиту. Заранее огромное спс.
5
09 января 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: NextTime
То есть в списке название элемента, а в массиве описание элемента. При нажатии на название элемента в списке в тестовом поле появляется описание.


Отказаться от этого.
ListBox вполне способен отображать "неважно-какие-объекты".
Для эффективного решения задачи требуется научиться пользоваться:
1) классом System.Collections.Generic.List<T>.
2) компонентом BindingSource


Кладем на форму компонент ListBox (назовем его box), кладем BindingSource (назовем box_source). Свойству DataSource листбокса назначаем box_source. Для отображения описания текущего элемента кладем TextBox (называем txt_description). Больше ничего с формой не делаем.

В коде объявляем класс вида:

Код:
public class MyItem {

    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 partial class Form1 : Form {
    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.
1.8K
09 января 2009 года
NextTime
217 / / 19.12.2007
Немного недогнал... С List<T> я работатал а со связкой BindingSource нет....
Так вот.... у теб все прекрасно в коде. Одно не понял....
Добавили в список новые элементы:
 
Код:
_items.Add(new MyItem("item 1", "Hello"));
_items.Add(new MyItem("item 2", "World"));
_items.Add(new MyItem("item 3", "!"));


Потом в процедуре указываем источник Box_source:
 
Код:
box_source.DataSource = _items;

У ListBox указываем какое поле класса отображать:
 
Код:
box.DisplayMember = "Name";

А где заполнение ListBox, или связка его с items, чтобы он автоматически отображал элементы items.... Т.е. как и где ListBox узнает о изменении коллекции _items? Т.е.2, как в ListBox попадают элементы?
 
Код:
// txt_description будет автоматически привязываться к текущему выделенному объекту
        txt_description.DataBindings.Add(new Binding("Text", box_source, "Description"));

Все догнал с этим кодом, который выше, кроме: Мы добавили связующее поле "Description"... А где и как он узнает, что именно по SelectedIndex нужно это делать? Можешь прокомментировать код и для чайников... хотя я вроде все понимаю кроме этих моментов.
И попрошу без отправки в MSDN ибо был там и раздела "Cods by hardcase" увы там нет... и еще... ты пишешь на C(++,# я незнаю, ибо с ними не работал и неразличаю), а мне надо на VB.Net, я обычно легко переводил твой код, но с:
 
Код:
public MyItem(string name, string description) {
this._name = name;
this._description = description;
}

не смог... это же конструктор? я не смог найти в MSDN как сними работать, а именно: параметры:string name, string description по идее нужно мне написать:
 
Код:
public MyItem(Byval name as string,Byval description as string)
Me._name = name [COLOR="Green"]' Ну или что то вместо Me[/COLOR]
Me._description = description
End Что-то(?)

Но он ругается на параметры, просит массив с границей 0 и испоьзовать "To". Помоги пожалуйста
P.S. Я конечно понимаю, что тебе проще создать свой алгоритм, который в 1000 проще и мощней (не спорю), но мне же всю свою прогу переделывать... Может ты мой алгоритм доделать поможешь?
5
09 января 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: NextTime
Немного недогнал... С List<T> я работатал а со связкой BindingSource нет....
Так вот.... у теб все прекрасно в коде. Одно не понял....
Добавили в список новые элементы:
 
Код:
_items.Add(new MyItem("item 1", "Hello"));
_items.Add(new MyItem("item 2", "World"));
_items.Add(new MyItem("item 3", "!"));
Потом в процедуре указываем источник Box_source:
 
Код:
box_source.DataSource = _items;
У ListBox указываем какое поле класса отображать:
 
Код:
box.DisplayMember = "Name";
А где заполнение ListBox, или связка его с items, чтобы он автоматически отображал элементы items.... Т.е. как и где ListBox узнает о изменении коллекции _items?

ListBox тягает элементы из BindingSource-а, а тот - из коллекции _items. У box и у box_source есть свойство DataSource, только box-у мы в дизайнере назначили box.DataSource = box_source. А потом в коде (метод BindBoxItems) мы при каждой модификации коллекции _items назначаем box_source.DataSource = _items (с предварительным обнулением).


Цитата: NextTime

 
Код:
// txt_description будет автоматически привязываться к текущему выделенному объекту
        txt_description.DataBindings.Add(new Binding("Text", box_source, "Description"));
Все догнал с этим кодом, который выше, кроме: Мы добавили связующее поле "Description"... А где и как он узнает, что именно по SelectedIndex нужно это делать?

txt_description не лезет по SelectedIndex в листбокс box. Он лезет по свойству Current у биндинг сурса box_source. Лист бокс всегда будет изменять это свойство у box_source при выделении элементов.

Цитата: NextTime

 
Код:
public MyItem(string name, string description) {
this._name = name;
this._description = description;
}
не смог... это же конструктор?

Да, это конструктор. И объявлять его нужно по правилам VB.NET. Проблема в том, что я вот так сходу не пишу на VB.NET - мне быстрее написать на C# или Nemerle. ;)

Код:
Public Class MyItem

    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
341
10 января 2009 года
Der Meister
874 / / 21.12.2007
Как вариант:
Код:
public class MyItem {

    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;

Такой вариант хорош, если сортировка - часть представления и не играет роли в бизнес-логике.
5
10 января 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: Der Meister
Такой вариант хорош, если сортировка - часть представления и не играет роли в бизнес-логике.


Кстати да :D
Я сам уже давно привык к биндингам, и по-тупому делать разучился.

1.8K
11 января 2009 года
NextTime
217 / / 19.12.2007
Der Meister, чтобы сортировать в списке по Name можно будет использовать свойство Sorted? а в примере hardCase как сортировать?
341
11 января 2009 года
Der Meister
874 / / 21.12.2007
Цитата: NextTime
Der Meister, чтобы сортировать в списке по Name можно будет использовать свойство Sorted? а в примере hardCase как сортировать?

Даже если нельзя в том виде, в котором приведены примеры, научить классы сравнивать себя друг с другом несложно.
Для примера hardcase:

Код:
public class MyItem : IComparable<MyItem> {

    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();
1.8K
14 января 2009 года
NextTime
217 / / 19.12.2007
А что, если я хочу позволить пользователю выбирать несколько элементов из списка ListBox? я поставлю SelecionMode=MultiExtended, и что? BindingSource не повешается? Он будет ведь Отслеживать SelectedIndex и BindingSource.Current будет =SelectedIndex, а не SelectedIndices, верно? Если верно - то все должно быть норм и не повешается)))
5
14 января 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: NextTime
BindingSource не повешается? Он будет ведь Отслеживать SelectedIndex и BindingSource.Current будет =SelectedIndex, а не SelectedIndices, верно? Если верно - то все должно быть норм и не повешается)))


Да. Current свойство будет соответствовать первому элементу в выделении.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог