2012-04-10 14 views
5

संपादित में CollectionViewSource स्रोत बदलने: मैं सिर्फ 3 फ़ाइलों MainWindow.xaml, MainWindow.xaml.cs, और MainWindowViewModel.cs ( नीचे सूचीबद्ध) के साथ एक नई VS2010 WPF appilication बनाया। अगर कोई वास्तव में सहायक महसूस करता है तो आप सेकंड में समस्या को दोबारा बना सकते हैं (कॉपी/पेस्ट)। जब आप ऐप चलाते हैं तो डेटाग्रिड स्ट्रिंग "ओल्डकोलेक्शन" प्रदर्शित करेगा जो गलत है। यदि आप MyCollection में आइटम्ससोर्स बाइंडिंग को बदलते हैं तो यह "न्यूकॉलेक्शन" प्रदर्शित करता है जो सही है।एक MVVM दुनिया

पूर्ण विवरण: सबसे पहले मेरे डेटासोर्स के साथ MyCollection के साथ डेटाग्रिड था। मुझे एक विधि अद्यतन चयन की आवश्यकता है जो MyCollection में एक नया ObservableCollection <> असाइन करता है। MyCollection को UI अद्यतनों के लिए NotifyPropertyChange के अतिरिक्त के साथ।

अगला समूहकरण को सक्षम करने के लिए संग्रहव्यूसोर्स पेश करना आवश्यक हो गया। UI को MyCollectionView से बाध्य करने के साथ, अपडेट कोलेक्शन पर कॉल का कोई प्रभाव नहीं पड़ता है। डीबगर पुष्टि करता है कि MyCollectionView में हमेशा प्रारंभिक MyCollection शामिल है। मैं अपने न्यूकोलेक्शन को दृश्य में प्रतिबिंबित करने के लिए कैसे प्राप्त कर सकता हूं? मैंने View.Refresh(), बाइंडिंग संग्रहव्यूसोर्स, और अनगिनत अन्य रणनीतियों का प्रयास किया है।

नोट: मुख्य रूप से अन्य संग्रह आइटम में परिवर्तन से संबंधित हैं, ताज़ा कॉल किए बिना दृश्य (समूह/सॉर्टिंग) को अपडेट नहीं करते हैं। मेरी समस्या यह है कि मैं CollectionViewSource पर एक नया संग्रह संग्रहीत कर रहा हूं और दृश्य/यूआई कभी नहीं बदलता है।

// MainWindow.xaml 
<Window x:Class="CollectionView.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <DataGrid Name="grid" ItemsSource="{Binding MyCollectionView}" /> 
    </Grid> 
</Window> 

//MainWindow.xaml.cs 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows; 

namespace CollectionView 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new MainWindowViewModel(); 
     } 
    } 
} 

//MainWindowViewModel.cs: 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Collections.ObjectModel; 
using System.Windows.Data; 
using System.ComponentModel; 

namespace CollectionView 
{ 
    class MainWindowViewModel : INotifyPropertyChanged 
    { 
     public MainWindowViewModel() 
     { 
      MyCollection = new ObservableCollection<MyObject>() { new MyObject() { TestString = "OldCollection" } }; 

      MyCollectionViewSource = new CollectionViewSource(); 

      // Bind CollectionViewSource.Source to MyCollection 
      Binding MyBind = new Binding() { Source = MyCollection }; 
      BindingOperations.SetBinding(MyCollectionViewSource, CollectionViewSource.SourceProperty, MyBind); 

      // The DataGrid is bound to this ICollectionView 
      MyCollectionView = MyCollectionViewSource.View; 

      // This assignment here to demonstrate that View/UI does not update to show "NewCollection" 
      MyCollection = new ObservableCollection<MyObject>() { new MyObject() { TestString = "NewCollection" } }; 
     } 

     // Collection Property 
     // NotifyPropertyChanged added specifically to notify of MyCollection re-assignment 
     ObservableCollection<MyObject> _MyCollection; 
     public ObservableCollection<MyObject> MyCollection 
     { 
      get { return _MyCollection; } 
      set 
      { 
       if (value != _MyCollection) 
       { 
        _MyCollection = value; 
        NotifyPropertyChanged("MyCollection"); 
       } 
      } 
     } 

     public CollectionViewSource MyCollectionViewSource { get; private set; } 
     public ICollectionView MyCollectionView { get; private set; } 

     // Method updates MyCollection itself (Called via ICommand from another ViewModel) 
     public void UpdateCollection(ObservableCollection<MyObject> NewCollection) 
     { 
      MyCollection = NewCollection; 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void NotifyPropertyChanged(String info) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(info)); 
      } 
     } 
    } 

    class MyObject 
    { 
     public string TestString { get; set; } 
    } 
} 

धन्यवाद,

उत्तर

4

मैं निम्नलिखित दो समाधानों में से एक चुनूंगा।

सबसे पहले, आप अपना ObservableCollection ले सकते हैं और एक बार ICollectionView (समूहबद्ध, सॉर्टिंग) बना सकते हैं।ObservableCollection को बदलने के बजाय आप .Clear() का उपयोग कर सकते हैं और नए संग्रह से आइटम जोड़ सकते हैं। इसमें आपके समूह और सॉर्टिंग को तोड़ने का अतिरिक्त बोनस है।

दूसरा दृष्टिकोण: जब भी आप अपना ObservableCollection बदलते हैं तो आपको सॉर्टिंग और ग्रुपिंग के लिए एक नया ICollectionView बनाना होगा।

this._view = (ICollectionView)CollectionViewSource.GetDefaultView(this.MyCollection); 

आप बस अपने संग्रह के लिए बाध्य करता है, तो आप defaultView

<DataGrid Name="grid" ItemsSource="{Binding MyCollection}" /> 

लेने के लिए और आप सामान बाध्यकारी अपने CollectionViewSource कोड फेंक सकता कर सकते हैं।

0

समस्या निश्चित रूप से तथ्य यह है कि आप अपने MyCollection संपत्ति के स्रोत बाध्यकारी नहीं कर रहे हैं, तो आप इसे एक बार बताए रहे हैं और इसे फिर से अद्यतन हो जाता है कभी नहीं।

आप की तरह कुछ करना चाहिए निम्नलिखित:

MyCollectionViewSource = new CollectionViewSource(); 
Binding binding = new Binding(); 
binding.Source = MyCollection; 
BindingOperations.SetBinding(MyCollectionViewSource , 
           CollectionViewSource.SourceProperty, 
           binding); 

मैं माफी माँगता हूँ अगर इसके बाद के संस्करण में सुधार करने के बिना तुरंत काम नहीं करता है - यह आम तौर पर बात के प्रकार मैं XAML में स्थापित किया है, यह बहुत है, क्योंकि वहाँ आसान है।

<CollectionViewSource Source="{Binding MyCollection}" /> 

भी देखें: How do I change the binding of a CollectionView.Source?

+0

यह समस्या इतनी निराशाजनक है कि मैंने प्रश्न संपादित किया (संपादित अनुभाग देखें) ताकि कोई भी सेकंड को इस मुद्दे को पुन: उत्पन्न कर सके। आपके सुझाव के अनुसार मैंने उपरोक्त कोड पर संग्रह ViewSource बाध्यकारी जोड़ा, लेकिन इसका कोई प्रभाव नहीं पड़ा। – aidesigner

0

तथ्य यह है कि बाध्यकारी नहीं कर रहा है अविश्वसनीय रूप से अजीब है। मुझे Xceed DataGridCollectionViewSource के साथ एक ही समस्या का सामना करना पड़ा - लेकिन मुझे लगता है कि ऐसा इसलिए था क्योंकि Xceed खराब हो गया था।

मेरा समाधान वास्तव में अंतर्निहित संग्रह को प्रतिस्थापित करने के लिए और इसे प्रोग्रामेटिक रूप से पुन: कॉन्फ़िगर करने के लिए एक नया नया डेटाग्रिड कोलेक्शनव्यूसोर्स बनाना था, और उसके बाद myDataGrid.Source प्रॉपर्टी को नए DataGridCollectionViewSource पर इंगित करने के लिए अद्यतन करें। यही कारण है कि वैकल्पिक हल निश्चित रूप से काम करेंगे, लेकिन है कि पूरी तरह बाइंडिंग के प्रयोजन है, जो काम करना चाहिए धरा:

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    //Xceed DataGridCollectionView are terrible and do not update when the bound table changes, so we need to replace them each change. 
    if (e.PropertyName == "MyCollection") 
    { 
     DataGridCollectionView GridView = new DataGridCollectionView(MyViewModel.MyCollection.DefaultView); 
     GridView.SortDescriptions.Add(new SortDescription("DataSetID", ListSortDirection.Ascending)); 
     uiMyCollectionGrid.ItemsSource = GridView; 
    } 
} 

हो सकता है कि यह जानवर बल समाधान आपकी समस्या का समाधान कर सकते हैं? मैं समझता हूं कि आप इस पर विचार करना भी नहीं चाहते हैं क्योंकि यह बहुत गंदा है।

+0

कोशिश के लिए धन्यवाद, लेकिन मैंने आपके कारणों के लिए कुछ और पसंद किया है। इसके अलावा मैं एमवीवीएम पैटर्न के साथ अपने व्यूमोडेल से एक्स: कुंजी uiMyCollectionGrid तक नहीं पहुंच सकता। दिलचस्प रूप से CollectionViewSource दस्तावेज़ http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.aspx का कहना है कि "संग्रह परिवर्तन ईवेंट द्वारा उठाए गए परिवर्तन विचारों के लिए प्रचारित हैं"। शायद यह प्रॉपर्टी चेंज खा रहा है जो वास्तव में आग लगती है जब संपत्ति MyCollection एक नया मान असाइन करती है। – aidesigner