none
Хранение, отображение, сортировка, фильтрация списка объектов? RRS feed

  • Вопрос

  • Создал класс хранящий определенный объем данных, но так же содержащий различные статические методы. Необходимо хранить таких экземпляров не более тысячи, но я думаю в основном их не будет более 100. Кроме отображения в списке с объектами точно будет производиться фильтрация и выборки по неуникальному ключу.

    Почитав материал меня заинтерисовал объект DataTable, особенно его возможность поддерживать несколько DataView, ну и проблемм с отображением нет. Но загвоздка в том что все примеры что я встретил предлагают создать структуру в DataTable похожую на мой класс и потом производить с ним эти самые фильтрации и выборки. Но мне нужны не только хранимые поля, но и методы их обработки и статические данные - по сути я хочу увидеть сам класс.

    Нет ничего подобного DataTable<T>? Или как подобное делаете вы?

    6 декабря 2011 г. 14:59

Ответы

  • >Как можно реализовать их отображение, фильтрацию, сортировку?

    LINQ to object http://www.codeproject.com/KB/linq/LINQtoObjects_CS.aspx

     

    • Помечено в качестве ответа PhantomSL 8 декабря 2011 г. 13:33
    7 декабря 2011 г. 18:45
  • >И вообще никто не может дать ссылку или рассказть на примере об опыте работы с любым ЛОКАЛЬНЫМ списком как со справочником (опять же повторюсь: сортировка, фильтрация). Просто вроде задача типичная, а примеров найти не могу!

    Фильтрация и сортировка списка - это банальные вещи, которые делаются на уровне кода без всяких дополнительных компонентов.

    Пример:

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApplication111
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<MyDataObject> list = new List<MyDataObject>(){ 
                    new MyDataObject() { FieldA = 250, FieldB = "Иванов" },
                    new MyDataObject() { FieldA = 425, FieldB = "Петров" },
                    new MyDataObject() { FieldA = 125, FieldB = "Иванов" } };
                //сортировка
                list.Sort((a, b) => a.FieldA.CompareTo(b.FieldA));
                //фильтрация
                var filteredList = Filtration<MyDataObject>(list, "FieldB", "Иванов");
                //вывод
                foreach (var obj in filteredList)
                    Console.WriteLine(obj.FieldA + " " + obj.FieldB);
            }
    
            public static IEnumerable<T> Filtration<T>(IEnumerable<T> list, string fieldName, object filterValue)
            {
                var fi = typeof(T).GetProperty(fieldName);
                foreach (var obj in list)
                    if (fi.GetValue(obj, null).Equals(filterValue))
                        yield return obj;
            }
        }
    
        public class MyDataObject
        {
            public int FieldA { get; set; }
            public string FieldB { get; set; }
        }
    }
    
    


    >Если будет использоваться в качестве списка "Dictionary, SortedList и т.п.", будет ли LinQ при сортировках выборках и поисках использовать их индексы и хеши (естественно для тех полей где это возможно) или будет сплошной перебор?

    Если вы будете использовать Dictionary, то LINQ вам наврядли вообще как-то поможет. LINQ это всего лишь синтаксический сахар, который скрывает за собой обычный foreach.

    • Помечено в качестве ответа PhantomSL 8 декабря 2011 г. 13:34
    8 декабря 2011 г. 8:48

Все ответы

  • Нет ничего подобного DataTable<T>? Или как подобное делаете вы?

    DataTable-ы - имеют то, что и должны иметь любые таблицы колонки, строки, связи, но не методы. Если нужны и методы, то посмотрите в сторону DataSet-ов.

    в основном:

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

    2. либо используются типизированные DataSet-ы (насчет второго ничего не скажу - ими не пользуюсь)


    как-то так...
    • Изменено A.G.Sedov 7 декабря 2011 г. 5:45
    7 декабря 2011 г. 5:36
  • Хорошо зайдем с другой стороны:

    У нас есть данные List<T> или лубой другой коллекции.

    Как можно реализовать их отображение, фильтрацию, сортировку?

    Связка: List<T> -> BindingSource -> DataGridView дают только отображение.

     

    P.S. Просто у меня возникает такое чувство что я нев том инете ищу, все сплошь и рядом пользуются колекциями, но ниге нормального примера их вывода и дальнейшего взаимодействия. А примеры из книг Console.Write ...

    7 декабря 2011 г. 15:37
  • >Как можно реализовать их отображение, фильтрацию, сортировку?

    LINQ to object http://www.codeproject.com/KB/linq/LINQtoObjects_CS.aspx

     

    • Помечено в качестве ответа PhantomSL 8 декабря 2011 г. 13:33
    7 декабря 2011 г. 18:45
  • Ваше сообщение без сомнения можно считать ответом. Только подскажите мне еще парочку вещей:

    1. Если планирую потом эти данные еще и отображать (со всеми последствиями мигание при перерисовке, "сбивание" курсора) перерисовку лучше делать с помощью тогоже BindingSource или использовать виртуальный режим DataGridView?

    2. Использование LINQ на списках можно ускорить (оптимизировать) индексами?

    3.  Обратиться к свойству можно как-то по имени?

    jobDataList = (

    from jd injobDataList orderby jd.UserID descending select jd).ToList();

    К примеру при клике на заголовок столбца я получу string "FieldName", а как его превратить в jd.UserID. В SQL все красиво из-за того это это текст, в DataTable можно обращаться по имени поля?

    А здесь как CASE на все случаи жизни?

     

     

    • Изменено PhantomSL 7 декабря 2011 г. 20:51
    7 декабря 2011 г. 19:22
  • > предлагают создать структуру в DataTable похожую на мой класс и потом производить с ним эти самые фильтрации и выборки. Но мне нужны не только хранимые поля, но и методы их обработки и статические данные [...] планирую потом эти данные еще и отображать (со всеми последствиями мигание при перерисовке, "сбивание" курсора)
     
     
    вместо DataTable можно использовать BindingList.
    данные можно привязать к DataGridView. работает без проблем.
    ниже пример привязки 100 тыс. элементов.
     

    using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication9
    {
        class Data
        {
            public string Value1 { get; set; }
            public string Value2 { get; set; }
        }
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                var bl = new BindingList<Data>();
                for (int i=0; i < 100000; i++) bl.Add(new Data { Value1 = i.ToString() });
                new DataGridView { Parent = this, Dock = DockStyle.Fill, DataSource = bl };
            }
        }
    }
    
       

    8 декабря 2011 г. 4:55
  • Хорошо зайдем с другой стороны:

    У нас есть данные List<T> или лубой другой коллекции.

    Как можно реализовать их отображение, фильтрацию, сортировку?

    Связка: List<T> -> BindingSource -> DataGridView дают только отображение.

     

    P.S. Просто у меня возникает такое чувство что я нев том инете ищу, все сплошь и рядом пользуются колекциями, но ниге нормального примера их вывода и дальнейшего взаимодействия. А примеры из книг Console.Write ...

     

    Фильтрация, сортировка, пейджинг, группировка и т.д. и т.п. - это всё делается на уровне данных

    Данные вы берете из БД?  Запрос получающих данные должен и отсортировать, и отфильтровать, и сгруппировать и всё на свете.

    Т.е. в List<T> данные уже должны быть в нужном виде.


    • Изменено A.G.Sedov 8 декабря 2011 г. 6:14
    8 декабря 2011 г. 6:13
  • To A.G.Sedov:

    Данные храняться локально и получаются в рассортрованном виде.

    По совету Algol36 и учитывая что их до 1000 скорее всего буду испольовать LINQ. Остается правда пару вопросов озвученных выше:

    1. Если планирую потом эти данные еще и отображать (со всеми последствиями мигание при перерисовке, "сбивание" курсора) перерисовку лучше делать с помощью тогоже BindingSource или использовать виртуальный режим DataGridView?

    2. Использование LINQ на списках можно ускорить (оптимизировать) индексами?

    3.  Обратиться к свойству можно как-то по имени?

    jobDataList = (from jd injobDataList orderby jd.UserID descending select jd).ToList();

    К примеру при клике на заголовок столбца я получу string "FiealName", а как его превратить в jd.UserID. В SQL все красвиво из-за того что это текст, в DataTable можно обращаться по имени поля. А как в LINQ?

    • Изменено PhantomSL 8 декабря 2011 г. 8:00
    8 декабря 2011 г. 7:59
  • To Malobukv :

    У биндинг листа при привязке к DataGridView не работает фильтрация и сортировка. Нужно реализовывать какой-то свой интерфейс, но в C# я пока начинающий и не возьмусь. Правда находил ссылку: http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=579972&msg=5982778

    8 декабря 2011 г. 8:04
  • >1. Если планирую потом эти данные еще и отображать (со всеми последствиями мигание при перерисовке, "сбивание" курсора) перерисовку лучше делать с помощью тогоже BindingSource или использовать виртуальный режим DataGridView?

    Это ни как не относится к LINQ. Если вам нужна производительность - лучше конечно виртуальный режим.

    >2. Использование LINQ на списках можно ускорить (оптимизировать) индексами?

    Нет, в LINQ to Object - нельзя. Если у вас на входе List, то время доступа к нему никак уменьшить нельзя. Если нужен поиск по ключу - нужно использовать Dictionary, SortedList и т.п.

    >3. Обратиться к свойству можно как-то по имени?

    Не очень понял вопрос. В LINQ и так идет обращение по имени свойства. Если вы имеете ввиду как обратится не указывая имя объекта с точкой, то по моему так сделать нельзя (могу ошибаться).

    8 декабря 2011 г. 8:05
  • To Angol36:

    По поводу пункта 2: Если будет использоваться в качестве списка "Dictionary, SortedList и т.п.", будет ли LinQ при сортировках выборках и поисках использовать их индексы и хеши (естественно для тех полей где это возможно) или будет сплошной перебор?

    И вообще никто не может дать ссылку или рассказть на примере об опыте работы с любым ЛОКАЛЬНЫМ списком как со справочником (опять же повторюсь: сортировка, фильтрация). Просто вроде задача типичная, а примеров найти не могу!

    8 декабря 2011 г. 8:12
  • >И вообще никто не может дать ссылку или рассказть на примере об опыте работы с любым ЛОКАЛЬНЫМ списком как со справочником (опять же повторюсь: сортировка, фильтрация). Просто вроде задача типичная, а примеров найти не могу!

    Фильтрация и сортировка списка - это банальные вещи, которые делаются на уровне кода без всяких дополнительных компонентов.

    Пример:

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApplication111
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<MyDataObject> list = new List<MyDataObject>(){ 
                    new MyDataObject() { FieldA = 250, FieldB = "Иванов" },
                    new MyDataObject() { FieldA = 425, FieldB = "Петров" },
                    new MyDataObject() { FieldA = 125, FieldB = "Иванов" } };
                //сортировка
                list.Sort((a, b) => a.FieldA.CompareTo(b.FieldA));
                //фильтрация
                var filteredList = Filtration<MyDataObject>(list, "FieldB", "Иванов");
                //вывод
                foreach (var obj in filteredList)
                    Console.WriteLine(obj.FieldA + " " + obj.FieldB);
            }
    
            public static IEnumerable<T> Filtration<T>(IEnumerable<T> list, string fieldName, object filterValue)
            {
                var fi = typeof(T).GetProperty(fieldName);
                foreach (var obj in list)
                    if (fi.GetValue(obj, null).Equals(filterValue))
                        yield return obj;
            }
        }
    
        public class MyDataObject
        {
            public int FieldA { get; set; }
            public string FieldB { get; set; }
        }
    }
    
    


    >Если будет использоваться в качестве списка "Dictionary, SortedList и т.п.", будет ли LinQ при сортировках выборках и поисках использовать их индексы и хеши (естественно для тех полей где это возможно) или будет сплошной перебор?

    Если вы будете использовать Dictionary, то LINQ вам наврядли вообще как-то поможет. LINQ это всего лишь синтаксический сахар, который скрывает за собой обычный foreach.

    • Помечено в качестве ответа PhantomSL 8 декабря 2011 г. 13:34
    8 декабря 2011 г. 8:48
  • Я под фразой пример справочника имел ввиду больше о взаимодействии с контролом для отображения. К примеру даже DataGridView при моей привязке не отобрапжает возможности сортировки. Пример описывающий взаиможействие даннных и отображения...

    То что с данными мне надо копаться, разбираться и учиться самому это понятно. Благо в C# этих механизмов хватает. Просто в контролах пока понаходишь все необходимые события и свойства пару раз обожжешся, а на примере статьи можно пару грабель и переступить.

    8 декабря 2011 г. 11:06
  • >К примеру даже DataGridView при моей привязке не отобрапжает возможности сортировки

    DataGridView умеет сортировать только если он сам содержит данные, если источник данных - внешний, нужно сортировать источник (как тут уже писали).

    Для отображения глифа сортировки: DataGridViewColumnHeaderCell.SortGlyphDirection

    8 декабря 2011 г. 13:00
  • > У биндинг листа при привязке к DataGridView не работает фильтрация и сортировка. Нужно реализовывать какой-то свой интерфейс
     

       
    в linq есть OrderBy и OrderByDescending.
    ниже пример, который хранит данные в базе данных sql server (express версия бесплатна).
    база данных создается автоматически.
    в примере есть фильтрация и сортировка. есть возможность редактирования значений в DataGridView.
    изменения сохраняются в базе данных при закрытии формы.
     
     

    using System.Data.Entity;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication9
    {
        class Item
        {
            public int Id { get; set; }
            public string Value { get; set; }
        }
        class DataStore : DbContext
        {
            public DbSet<Item> items { get; set; }
            protected override void OnModelCreating(DbModelBuilder m)
            {
                base.OnModelCreating(m);
                m.Entity<Item>().HasKey(e => e.Id).ToTable("Items");
            }
        }
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                var ds = new DataStore();
                if (ds.Database.CreateIfNotExists())
                {
                    for (int i = 0; i < 30; i++)
                        ds.items.Add(new Item { Value = "v" + i });
                    ds.SaveChanges();
                }
                var res = from x in ds.items where x.Value.EndsWith("2") select x;  // фильтрация
                var dg = new DataGridView
                {
                    Parent = this,
                    Dock = DockStyle.Fill,
                    AutoGenerateColumns = false,
                    AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
                    DataSource = res.ToList()
                };
                dg.Columns.AddRange(
                    new DataGridViewTextBoxColumn
                    {
                        HeaderText = "Value",
                        DataPropertyName = "Value",
                        SortMode = DataGridViewColumnSortMode.Programmatic
                    });
                this.FormClosing += (s, e) => ds.SaveChanges();
                this.Menu = new MainMenu();
                this.Menu.MenuItems.Add("sort asc", delegate { dg.DataSource = res.OrderBy(i => i.Value).ToList(); });
                this.Menu.MenuItems.Add("sort desc", delegate { dg.DataSource = res.OrderByDescending(i => i.Value).ToList(); });
            }
        }
    }
    
     

    8 декабря 2011 г. 13:42