2017-12-21 6 views
0

So ist die Sache, gestern wollte ich eine Suchleiste zum Filtern eines Datagrid machen. Es ist mir gelungen, dies zu tun, aber als ich es heute durchgesehen habe, habe ich gemerkt, dass ich keine Ahnung habe, warum es funktioniert. Hier ist, was mich verwirrend ist:Filtern auf Datagrid mit WPF MVVM, es funktioniert, aber ich weiß nicht warum

Grundsätzlich habe ich ein DataGrid mit ItemsSource auf eine ObservableCollection namens Equipments gesetzt. Um auf Geräten zu filtern, habe ich auch eine ICollectionView namens EquipmentView erstellt, die nur ein Spiegel der Ausrüstungen ist, die ich filtern kann.

public async Task LoadAsync() 
    { 
     try 
     { 
      var lookup = await _equipmentLookupDataService.GetEquipmentLookupAsync(); 
      Equipments.Clear(); 
      foreach (var item in lookup) 
      { 
       Equipments.Add(item); 
      } 
      EquipmentView = CollectionViewSource.GetDefaultView(Equipments); 
      EquipmentView.Filter = new Predicate<object>(Filter); 
     } 
     catch (Exception e) 
     { 
      MessageBox.Show(e.Message, "An error occurred", MessageBoxButton.OK, MessageBoxImage.Warning); 
      //create new error object from the exception and add to DB 
      Error error = new Error 
      { 
       ErrorMessage = e.Message, 
       ErrorTimeStamp = DateTime.Now, 
       ErrorStackTrace = e.StackTrace, 
       LoginId = CurrentUser.LoginId 
      }; 
      await _errorDataService.AddError(error); 
     } 
    } 

EquipmentView.Filter die Filter-Methode aufruft:

Equipments wird in dem Viewmodel aus einer Tabelle in der Datenbank wie folgt bevölkerten

public bool Filter(object obj) 
    { 
     var data = obj as EquipmentLookup; 

     if (EquipmentView != null) 
     { 
      if (!string.IsNullOrEmpty(_filterString)) 
      { 
       string allcaps = _filterString.ToUpper(); 
       return data.TypeName.StartsWith(_filterString) || data.TypeName.StartsWith(allcaps); 
      } 
      return true; 
     } 
     return false; 
    } 

Es gibt nur dann, wenn die Eigenschaft Type-Name beginnt Mit dem Filterstring, der die Zeichenfolge ist, die an meine Suchleiste gebunden ist.

Jetzt dachte ich, ich musste nur die DataGrid ItemsSource zu EquipmentView setzen. Wenn ich das tue, funktioniert alles gut und das Datagrid zeigt nur, was mit der Suchleiste übereinstimmt.

Offenbar, wenn ich die itemsSource auf dem Datagrid zurück zu Ausrüstungen setzt, funktioniert es noch, searchbar enthalten. Warum ist das? Soweit ich mich verstehe, sollte das Filtern von EquipmentView nichts an Geräten ändern, aber es scheint so zu sein.

Alles funktioniert gut, ich wünschte nur, ich wüsste warum.

auch XAML-Code für searchbar:

<TextBox Name="SearchBar" Margin="10 10 10 10" Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}"/> 

Datagrid:

 <DataGrid MaxHeight="800" 
      ItemsSource="{Binding Equipments}" 
      SelectedItem="{Binding SelectedEquipment, Mode=TwoWay}" 
      IsReadOnly="True" 
      CanUserReorderColumns="False" 
      SelectionMode="Single" 
      ColumnWidth="*"> 
      <DataGrid.ItemContainerStyle> 
       <Style TargetType="DataGridRow"> 
        <EventSetter Event="MouseDoubleClick" 
        Handler="Row_DoubleClick" /> 
       </Style> 
      </DataGrid.ItemContainerStyle> 
     </DataGrid> 
+2

Wenn Sie zu einer Sammlung binden, WPF tatsächlich zu der Standardansicht dieser Sammlung verbindlich. Die Ansicht ist nur ein Wrapper, mit dem Sie filtern, sortieren usw. können. – Manolo

Antwort

3

Von der WPF-Dokumentation:

Alle Kollektionen haben eine Standard-Collection. WPF bindet immer an eine Ansicht statt an eine Sammlung. Wenn Sie direkt an eine Auflistung binden, bindet WPF tatsächlich an die Standardansicht für diese Auflistung. Diese Standardansicht wird von allen Bindungen an die Auflistung gemeinsam verwendet, die alle direkten Bindungen an die Auflistung verursacht, um die Sortier-, Filter-, -Gruppe und aktuelle Elementmerkmale der einen Standardansicht zu teilen.

Jetzt in Ihrem Code, tun Sie dies:

EquipmentView = CollectionViewSource.GetDefaultView(Equipments); 
EquipmentView.Filter = new Predicate<object>(Filter); 
Verwandte Themen