2012-05-02 4 views
0

я "м пытается выяснить, если есть способ сделать следующее в C# 4.0:Collection, который ссылается на пункты другой коллекции

У меня есть ObservableCollection, который содержит большое количество пользовательских классов - позволяет называть его «MainCollection». Большая часть моего кода обновляет значения этих классов в MainCollection на постоянной основе, и все работает нормально.

Теперь мне нужно создать «коллекцию» [или что-то использовать в привязке DataContext WPF DataGrid ], который просто группирует классы в MainCollection по одному параметру в базовом классе.

Is t здесь можно сделать так, чтобы всякий раз, когда элементы MainCollection обновляются, так это новая «псевдо-коллекция».

+0

Пожалуйста, не префикс своих названий с "C# -" и тому подобными. Для этого нужны теги. –

ответ

1

Возможно, вы ищете CollectionView class :

Представляет представление для группировки, сортировки, фильтрации и навигации по сбору данных.

Однако

Вы не должны создавать объекты этого класса в коде. Чтобы создать представление коллекции для коллекции, которая реализует только IEnumerable, создайте объект CollectionViewSource, добавьте свою коллекцию в свойство Source и получите представление коллекции из свойства View.

Возможно, лучшим местом для начала будет How to: Sort and Group Data Using a View in XAML. Это и несколько других практических статей можно найти в нижней части страницы CollectionView.

+0

Глядя на это сейчас - определенно выглядит многообещающим! – keynesiancross

0

Можно ли просто выставить объект, который создает новую коллекцию по требованию? Что-то вроде

public List<Whatever> Items 
{ 
    get 
    { 
     return MainCollection.Where(x => [someCondition]).ToList(); 
    } 
} 
+0

возможно .. этот вопрос - это то, над чем я пытаюсь работать. Http://stackoverflow.com/questions/10419565/wpf-datagrid-bind-to-collection-of-cells – keynesiancross

1

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

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

0

Другими словами, вы хотели бы создать представление о вас MainCollection. Это похоже на работу для LINQ!

var newCollection = from item in MainCollection 
     group item by /*item condintion */ into g //use where for filtering 
     select new { Prop = g.Prop, Item = g }; 

Если вам нужно наблюдаемым, то просто передать последовательность в CTOR:

var observableColl = new ObservableCollection(newCollection); 
+0

Спасибо lukas - если я это сделаю хотя, будет ли наблюдаемый Coll обновляться, если MainCollection будет обновлен? – keynesiancross

+0

Нет, не будет. Необходимо снова выполнить запрос. –

+0

Ах - ок. для меня это не сработает. Спасибо хоть. – keynesiancross

0

Update MainCollection добавить эту группировку способность

class MainCollection 
{ 
    public Dictionary<TGroupBySingleParameter, TValue> TheLookup{get; private set;} 

    Update() 
    { 
     TheLookup.Add(//... 
     //do work 
    } 
} 
0

Вы можете создать FilteredCollection, который прослушивает события изменений для обновления фильтрованной коллекции. Это позволяет эффективно отфильтровать всякий раз, когда исходная коллекция изменилась.

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Collections.Specialized; 
using System.Linq; 

namespace ConsoleApplication26 
{ 
    class FilteredObservableCollection<T> : INotifyCollectionChanged, IEnumerable<T> 
    { 
     List<T> _FilteredCached; 
     ObservableCollection<T> Source; 
     Func<T,bool> Filter; 

     public FilteredObservableCollection(ObservableCollection<T> source, Func<T,bool> filter) 
     { 
      Source = source; 
      Filter = filter; 
      source.CollectionChanged += source_CollectionChanged; 
     } 

     void source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
     { 
      if (e.Action == NotifyCollectionChangedAction.Add) 
      { 
       var addedMatching = e.NewItems.Cast<T>().Where(Filter).ToList(); 
       _FilteredCached.AddRange(addedMatching); 
       if (addedMatching.Count > 0) 
       { 
        CollectionChanged(sender, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, addedMatching)); 
       } 
      } 
      else // make life easy and refresh fully 
      { 
       _FilteredCached = null; 
       CollectionChanged(sender, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
      } 
     } 

     public IEnumerator<T> GetEnumerator() 
     { 
      if (_FilteredCached == null) 
      { 
       _FilteredCached = Source.Where(Filter).ToList(); // make it easy to get right. If someone would call e.g. First() only 
       // we would end up with an incomplete filtered collection. 
      } 

      foreach (var filtered in _FilteredCached) 
      { 
       yield return filtered; 
      } 
     } 

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      return GetEnumerator(); 
     } 

     public event NotifyCollectionChangedEventHandler CollectionChanged = (o,e) => { }; 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      ObservableCollection<int> data = new ObservableCollection<int>(new int[] { 1, 2, 3, 4, 1 }); 
      var filteredObservable = new FilteredObservableCollection<int>(data, x => x > 2); 
      Print(filteredObservable); // show that filter works 
      data.Add(1); 
      Print(filteredObservable); // no change 
      data.Add(10); 
      Print(filteredObservable); // change 
      data.Clear(); 
      Print(filteredObservable); // collection is empy 
      data.Add(5); 
      Print(filteredObservable); // add item in filter range 
      data[0] = 1; 
      Print(filteredObservable); // replace it 
     } 

     static void Print<T>(FilteredObservableCollection<T> coll) 
     { 
      Console.WriteLine("Filtered: {0}", String.Join(",", coll)); 
     } 
    } 

} 

Это напечатает

Filtered: 3,4 
Filtered: 3,4 
Filtered: 3,4,10 
Filtered: 
Filtered: 5 
Filtered: 
Смежные вопросы