CollectionViewSource WPF



  • Na das ist mal interessant. Das wußte ich bisher auch noch nicht. Dank dir.


  • Administrator

    braunbär schrieb:

    Na das ist mal interessant. Das wußte ich bisher auch noch nicht.

    Ich habe es auch erst relativ spät mitbekommen. Irgendwie stand das nie in einem Tutorial oder ähnliches und ich treffe es auch heute noch selten an, dabei ist es äusserst praktisch.

    Ähnlich wie auch diese nette Funktion:
    http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.getdefaultview.aspx

    Obwohl man eine ObservableCollection an die View übergibt, kommt man trotzdem an das ICollectionView ran und somit auch an das selektierte Item, bzw. den entsprechenden Events. Man kann auch das selektierte Item damit setzen ( MoveCurrentToXXX ). Das ganze lässt sich dann auch prima in Unit Tests integrieren.

    Grüssli



  • Hallo nochmal

    Da hätte ich gleich noch eine Frage zum CurrentItem einer CollectionViewSource.
    Habe hier ein seltsames Verhalten.

    Im XAML funktioniert das mit dem CurrentItem, allerdings habe ich im Code ein Problem. Greife ich auf das CurrentItem in der View zu erhalte ich egal was in der ListView ausgewählt ist das erste Objekt in der List. Das allerdings nur beim ersten Mal.

    Wähle ich dann erneut einen Eintrag aus der ListView aus steht in CurrentItem das richtige drin.

    Was läuft da schief.



  • Das mit dem GetDefaultView habe ich auch nicht ganz verstanden.

    Wenn ich doch das CurrentItem will gehe ich doch einfach über .View.CurrentItem

    Wie wende ich GetDefaultView() an. Und was übergebe ich als Parameter. Das ist für mich noch verwirrend.



  • 1. Sorry nicht ListView sondern ListBox
    2. Ok das mit dem GetDefaultView ist mir nun klar
    Aber das Problem besteht auch hier in CurrentItem steht nicht drin was in der Liste ausgewählt wurde.


  • Administrator

    Hast du IsSynchronizedWithCurrentItem auf True gesetzt?

    Grüssli



  • Ja habe ich.

    Habe nun mal ein ganz einfaches Projekt gemacht.

    Eine ObservableCollection mit String. Diese habe ich der Source einer CollectionViewSource zugewiesen. Diese wiederum an eine ListView gebunden.

    Über einen Button lese ich auch hier nun das CurrentItem aus. Aber auch hier wird beim ersten mal immer der erste Eintrag angezeigt, egal was ausgewählt ist.

    Auch in der Liste wird nach Abfrage des CurrentItem der erste Wert selektiert.

    Verstehe ich nicht. Wie kann eine Abfrage eines Objekts den das Objekt ändern.


  • Administrator

    braunbär schrieb:

    Eine ObservableCollection mit String. Diese habe ich der Source einer CollectionViewSource zugewiesen. Diese wiederum an eine ListView gebunden.

    Hast du auch mal die CollectionViewSource ausgelassen? Wozu brauchst du diese überhaupt und wo erstellst du sie? XAML oder Code?

    Kannst du dein kurzes Beispiel hier präsentieren? Dann können wir ebenfalls damit testen. Oder sehen allenfalls gleich den Fehler 🙂

    Grüssli



  • So das ganz einfache Beispiel

    public partial class MainWindow : Window
    {
        public ObservableCollection<string> InternalHouses { get; set; }
    
        public CollectionViewSource Houses { get; set; } 
    
        public MainWindow()
        {
            InitializeComponent();
    
            DataContext = this;
    
            InternalHouses = new ObservableCollection<string>();
    
            InternalHouses.Add("house1");
            InternalHouses.Add("house2");           
            InternalHouses.Add("house3");
    
            Houses = new CollectionViewSource { Source = InternalHouses };
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var house = (string)Houses.View.CurrentItem;
        }
    }
    
    <StackPanel>
    
            <Button Click="Button_Click">Actual House</Button>
    
            <Label>Houses:</Label>
    
            <ListView Height="200"
                      IsSynchronizedWithCurrentItem="True"
                      ItemsSource="{Binding Houses.View}" />
    
        </StackPanel>
    

    In der ListView ist nun das erste Objekt ausgewählt. Wähle ich nun ein anderes Objekt aus. z.B. "House 2" und klicke dann den Button steht in CurrentItem "House 1" und in der ListView wird auch "House 1" wieder ausgewählt. Wähle ich nun nochmal "House 2" aus und klicke den Button steht in CurrentItem auch "House 2" drin


  • Administrator

    So funktioniert es:

    public partial class MainWindow : Window
    {
      public ObservableCollection<string> Houses { get; set; }
    
      public MainWindow()
      {
        InitializeComponent();
    
        DataContext = this;
    
        Houses = new ObservableCollection<string>();
    
        Houses.Add("house1");
        Houses.Add("house2");
        Houses.Add("house3");
      }
    
      private void Button_Click(object sender, RoutedEventArgs e)
      {
        var house = (string)CollectionViewSource.GetDefaultView(this.Houses).CurrentItem;
      }
    }
    

    Ich bin mir aktuell nur noch nicht ganz klar, wieso dem so ist, und werde mal danach suchen. Allerdings habe ich selber noch nie eine CollectionViewSource direkt im Code erstellt. Ich sehe keinerlei Vorteil darin. Überlass dies doch WPF.

    Grüssli



  • Also das ganze kommt von hier:

    http://www.xamlplayground.org/post/2009/07/18/Use-CollectionViewSource-effectively-in-MVVM-applications.aspx

    Wenn ich in meinem Code das CurrentItem, direkt nachdem ich die CollectionViewsource erstellt habe, einmal auslese. Dann funktioniert das nachher mit dem CurrentItem im Buttonhandler auch.
    Oder ich kann es auch mit MoveCurrentTo erstmal setzen dann funktioniert es auch.

    Meiner Meinung ist das ein Bug.


  • Administrator

    braunbär schrieb:

    Also das ganze kommt von hier:
    http://www.xamlplayground.org/post/2009/07/18/Use-CollectionViewSource-effectively-in-MVVM-applications.aspx

    Ich würde mal sagen, dem Mann war nicht bekannt, dass es die Funktion CollectionViewSource.GetDefaultView gibt. WPF erstellt automatisch eine CollectionViewSource , wenn man eine Liste an ein Control bindet. Es wird nie z.B. direkt die OberservableCollection angebunden.

    Daher kann man die ObservableCollection binden und falls man an die dazugehörige ICollectionView kommen möchte, kann man CollectionViewSource.GetDefaultView aufrufen.

    Grüssli



  • Achso die CollectionViewSource wird automatisch erstellt. Dachte ich muss die im XAML selber erstellen. Ja dann macht mir auch GetDefaultView sehr viel Sinn. Vielen Dank.

    Das andere ist meiner Meinung aber trotzdem ein bug 😉


Anmelden zum Antworten