2009-03-19 17 views
12

मेरे पास एक संग्रह ViewSource से जुड़ा एक WPF ListView है। इसका स्रोत किसी संपत्ति के लिए बाध्य है, जो उपयोगकर्ता बदल सकता है यदि उपयोगकर्ता कोई विकल्प चुनता है।संग्रहव्यूसोर्स फ़िल्टर स्रोत बदलते समय रीफ्रेश नहीं किया गया

जब किसी सूची में परिवर्तन के कारण सूची दृश्य स्रोत अपडेट किया जाता है, तो सबकुछ सही ढंग से अपडेट होता है, लेकिन संग्रह को VisualViewSource फ़िल्टर में किसी भी बदलाव को ध्यान में रखकर रीफ्रेश नहीं किया जाता है।

यदि मैं बदलती घटना में एक हैंडलर संलग्न करता हूं जो स्रोत प्रॉपर्टी के लिए बाध्य है, तो मैं दृश्य को रीफ्रेश कर सकता हूं, लेकिन यह अभी भी पुराना दृश्य है, क्योंकि बाइंडिंग ने अभी तक सूची को अपडेट नहीं किया है।

क्या स्रोत बदलते समय दृश्य को रीफ्रेश करने और पुन: मूल्यांकन करने का कोई शानदार तरीका है?

चीयर्स

+1

मामले में किसी को भी इस पाता है, यह अब पुराने हो चुके एक सा है। डब्ल्यूपीएफ 4.5 में, "लाइव" सॉर्टिंग, फ़िल्टरिंग और ग्रुपिंग की अनुमति देने के लिए नई सुविधाएं शामिल की गईं। देखें http://www.jonathanantoine.com/2011/10/05/wpf-4-5-%E2%80%93-part-10-live-shaping/ –

उत्तर

2

आप वास्तविक संग्रह उदाहरण CollectionViewSource.Source करने के लिए सौंपा बदल रहे हैं, या आप बस गुण है कि यह करने के लिए बाध्य कर रहा है पर PropertyChanged फायरिंग कर रहे हैं?

यदि Source संपत्ति सेट की गई है, तो नए स्रोत संग्रह में प्रत्येक आइटम के लिए फ़िल्टर को याद किया जाना चाहिए, इसलिए मैं कुछ और सोच रहा हूं। क्या आपने बाध्यकारी और देखने के बजाय मैन्युअल रूप से Source सेट करने का प्रयास किया है, यदि आप अभी भी अपना व्यवहार प्राप्त करते हैं?

संपादित करें:

आप CollectionViewSource.View.Filter संपत्ति, या CollectionViewSource.Filter घटना का उपयोग कर रहे हैं? CollectionView जब आप एक नया Source सेट करते हैं तो उड़ा दिया जाएगा, इसलिए यदि आपके पास CollectionView पर सेट है तो यह अब और नहीं होगा।

+0

हां, मैं संग्रह बदल रहा हूं, और आइटम सूची दृश्य में नए संग्रह को दर्शाते हुए अपडेट किया गया है। हालांकि फिल्टर का फिर से मूल्यांकन नहीं किया जाता है। इसे मैन्युअल रूप से करने में मदद नहीं मिली: ((संग्रहव्यूसोर्स) यह। स्रोत ["logEntryViewSource"]) स्रोत = _ appplication.CurrentLog.Entries.ObservableCollection – Steve

12

थोड़ा देर से शायद, लेकिन यह अन्य उपयोगकर्ताओं की मदद कर सकते हैं तो मैं वैसे भी पोस्ट करेंगे ...

एक PropertyChanged घटना के आधार पर CollectionView.Filter अपडेट किया जा रहा ढांचे द्वारा समर्थित नहीं है। इसके आसपास कई समाधान हैं।

1) आपके संग्रह के अंदर वस्तुओं पर IEDitableObject इंटरफ़ेस को कार्यान्वित करना, और फ़िल्टर पर आधारित संपत्ति को बदलते समय BeginEdit और EndEdit को कॉल करना। आप Dr.WPF उत्तम ब्लॉग यहाँ पर इस बारे में और अधिक पढ़ सकते हैं: Editable Collections by Dr.WPF

2) निम्नलिखित वर्ग बनाना और बदली हुई वस्तु पर RefreshFilter समारोह का उपयोग कर।

public class FilteredObservableCollection<T> : ObservableCollection<T> 
{ 
    public void RefreshFilter(T changedobject) 
    { 
     OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, changedobject, changedobject)); 
    }   
} 

उदाहरण:

public class TestClass : INotifyPropertyChanged 
{ 
    private string _TestProp; 
    public string TestProp 
    { 
     get{ return _TestProp; } 
     set 
     { 
      _TestProp = value; 
      RaisePropertyChanged("TestProp"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 


FilteredObservableCollection<TestClass> TestCollection = new FilteredObservableCollection<TestClass>(); 

void TestClass_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    switch (e.PropertyName) 
    { 
     case "TestProp": 
      TestCollection.RefreshFilter(sender as TestClass); 
      break; 
    } 
} 

TestClass वस्तु जब आप इसे बनाने के लिए, लेकिन मत भूलना eventhandler घृणाजनक जब वस्तु हटा दिया जाता है की PropertyChanged घटना के लिए सदस्यता लें, अन्यथा इस को जन्म दे सकती स्मृति लीक

या

TestClass में TestCollection सम्मिलित करें और TestProp सेटर अंदर RefreshFilter समारोह का उपयोग करें। किसी भी तरह, यहां जादू को NotifyCollectionChangedAction द्वारा काम किया जाता है। बदलें जो आइटम को पूरी तरह अद्यतन करता है।

+0

मैं वर्तमान में .NET 4.0 के साथ फंस गया हूं और IEDitableObject समाधान एक आकर्षण की तरह काम करता है। – Golvellius

+0

मुझे काम करने के लिए IEditableObject नहीं मिल सका। लेकिन FilteredObservableCollection महान काम करता है। समाधान के लिए धन्यवाद –

2

मुझे ऑब्जर्जेबल कोलेक्शन क्लास को उस स्थान पर विस्तारित करने के लिए एक विशिष्ट समाधान मिला जो here वाली वस्तुओं के गुणों में परिवर्तनों पर नज़र रखता है।

यहाँ मेरे द्वारा कुछ संशोधनों के साथ कि कोड है:

namespace Solution 
{ 
public class ObservableCollectionEx<T> : ObservableCollection<T> where T : INotifyPropertyChanged 
    { 
     protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      if (e != null) // There's been an addition or removal of items from the Collection 
      { 
       Unsubscribe(e.OldItems); 
       Subscribe(e.NewItems); 
       base.OnCollectionChanged(e); 
      } 
      else 
      { 
       // Just a property has changed, so reset the Collection. 
       base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 

      } 

     } 

     protected override void ClearItems() 
     { 
      foreach (T element in this) 
       element.PropertyChanged -= ContainedElementChanged; 

      base.ClearItems(); 
     } 

     private void Subscribe(IList iList) 
     { 
      if (iList != null) 
      { 
       foreach (T element in iList) 
        element.PropertyChanged += ContainedElementChanged; 
      } 
     } 

     private void Unsubscribe(IList iList) 
     { 
      if (iList != null) 
      { 
       foreach (T element in iList) 
        element.PropertyChanged -= ContainedElementChanged; 
      } 
     } 

     private void ContainedElementChanged(object sender, PropertyChangedEventArgs e) 
     { 
      OnPropertyChanged(e); 
      // Tell the Collection that the property has changed 
      this.OnCollectionChanged(null); 

     } 
    } 
} 
संबंधित मुद्दे