2010-11-17 2 views
0

Я пытаюсь улучшить проект Winforms, где данные, хранящиеся в таблице, хранятся в свойстве Tag ListViewItems. Когда datatable реорганизуется в List <T> (или на самом деле классы, содержащие списки), это очень помогло бы, если бы я мог создать свойство Tag generic с помощью подкласса ListView.Generic WinForms ListView (по отношению к тегу)

В лучшем мире я бы хотел, чтобы свойство Tag было заменено публичным тегом T {get; set;}, который обертывает base.Tag и отбрасывает его. Второй лучший вариант - это тег Obsoleting и предоставление нового свойства, такого как TypedTag, работающего, как указано выше.

Я думаю, что это связано с подклассом или составной агрегацией, по меньшей мере, ListView, ListViewItemCollection, SelectedListViewItemCollection и ListViewItem, и я не уверен, как это сделать.

Короче:

ListView<Employee> lvwEmployees; 

должно привести это быть возможным:

Employee selected = lvwEmployees.SelectedItems[0].TypedTag; 

И дать ошибку компиляции для этого:

DataRow selected = lvwEmployees.SelectedItems[0].TypedTag; 

возможно ли это? Это уже сделано? Проект - это dotnet 2.0, но я думаю, что попробую его обновить, если это поможет.

EDIT: Оказывается, что аргумент конструктора владельца - это все, что определенная коллекция должна подключаться к внутренней коллекции. Следовательно, следующие работы:

ListView a = new ListView(); 
a.Items.Add("Hello"); 
Assert.AreEqual(1, new ListView.ListViewItemCollection(a).Count); 

Это делает довольно простым создание общего помеченного ListView. Я отправлю полное решение позже. :)

EDIT2: Вот решение: http://thecarlr.blogspot.com/2010/11/generic-listview.html

EDIT3: Для поддержки дизайнера, просто добавить неофициальный общий подкласс и использовать. Пример: Если вы планируете использовать ListView <Employee> в форме, создайте ListViewEmployee: ListView <Employee> в другом файле и используйте ListViewEmployee в форме.

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

+0

Обсудить подобную тему на http://stackoverflow.com/questions/1126404/is-there-an-easy-way-to-associate-an-event-with-a-listviewitem – stuartd

ответ

0

Вот решение: http://thecarlr.blogspot.com/2010/11/generic-listview.html

Наслаждайтесь :)

/Carl

+0

Основная проблема с этим решением заключается в том, что общий список ListView <> не может использоваться в конструкторе. Поэтому, если вы не намереваетесь писать весь код пользовательского интерфейса (или публиковать редактирование Designer.cs), это решение не очень полезно. – Grammarian

+0

А, спасибо, что заметили и сообщили мне! Я должен посмотреть на это. :) –

+0

Кажется, проблема дизайнера действительно не проблема. Все, что мне нужно было сделать, это наследовать снова в не общий класс и использовать это вместо этого. –

1

Вы сделали неправильный общий класс. SelectedItems [0] - это ListViewItem, а не ListView.

Нет ничего, что можно было бы изменить, чтобы изменить свойства Items и SelectedItems. Вы можете, конечно, извлечь свой собственный класс из ListViewItem и просто добавить свойство, которое хотите сохранить. Нет необходимости в другом свойстве тега. Вам не составит труда добавить их, но вам нужно будет вернуться к производному классу, когда вы вернете их из коллекции Selected/Items.

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

+0

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

+0

Erm, вы можете сделать любое количество отдельных классов элементов списка. Пока они происходят из ListViewItem. В противном случае вы не сможете добавить их в коллекцию предметов ListView. В ListViewItem есть частные члены, которые необходимы для того, чтобы поддерживать Windows. –

+0

Да, но коллекция элементов ListView не является общей, поэтому ее нужно переопределить. –

0

VS Designer просто не может справиться с абстрактными или общие элементы управления (not for want of asking).

В одном направлении это ограничение заключается в том, чтобы написать безопасную упаковку типа по стандарту ListView.

Что-то вроде этого:

public class TypedListView<T> where T : class 
{ 
    public TypedObjectListView(ListView lv) { 
     this.lv = lv; 
    } 
    private ListView lv; 

    public virtual T SelectedObject { 
     get { return (T)this.lv.SelectedItems[0].Tag; } 
    } 

    // Lots more methods/properties 
} 

Вы создаете обычный ListView в конструкторе, а затем, когда вы хотите получить к нему доступ, создавать и использовать адаптер вместо этого. Как это:

var typedListView = new TypedListView<Employee>(this.listView1); 
Employee selectedEmployee = typedListView.SelectedObject; 

Вам нужно будет предоставить напечатанную версию каждых ListView свойств или методу вы хотели использовать.

Проект ObjectListView использует этот подход для создания TypedObjectListView, который выполняет именно то, что вы просите.

+0

Ничего себе, ObjectListView выглядит очень хорошо. Я должен изучить этот. Большое спасибо! –

+0

Мне нравится идея адаптера btw, но она не идеальна в том, что легко пройти обычную переменную, чтобы были строки с другими типами «тегов». –