2010-07-16 5 views
1

J'ai une application WPF qui utilise une base de données locale (actuellement) pour agir en tant que source de liaison. À l'aide des outils Visual Studio 2010, j'ai un modèle LINQ-SQL qui agit comme Datacontext pour la plupart des formulaires.Filtrage/recherche de données de base de données WPF

Ce que j'ai est un UserControl avec un TextBox et Datagrid. Le DataGrid ItemSource est défini sur l'événement UserControl.Loaded avec une table. Le TextBox a un événement assigné de sorte qu'une requête est exécutée sur la base de données lorsque le texte change et ItemSource est mis à jour sur le DataGrid.

Le problème avec ceci est le temps qu'il faut pour interroger la base de données. Comme je réaffecte la source d'éléments DataGrid pour chaque recherche.

  1. Dois-je chargeais tous les dossiers sur la UserControl Chargement - est-il possible de charger des documents de manière asynchrone dans un BackgroundWorker ou similaire? Ai-je besoin de réaffecter le DataGrid ItemsSource après chaque recherche ou est-ce un moyen plus efficace de filtrer les données?

Merci. Liam

<UserControl x:Class="Tracker.DocumentsView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <DataGrid AutoGenerateColumns="False" Margin="12,34,12,50" Name="dataGrid1"> 
      <DataGrid.Columns> 
       <DataGridTextColumn Binding="{Binding Path=ID}" Header="ID" /> 
       <DataGridTextColumn Binding="{Binding Path=Reference}" Header="Reference" /> 
       <DataGridTextColumn Binding="{Binding Path=Subject}" Header="Subject" /> 
      </DataGrid.Columns> 
     </DataGrid> 

     <TextBox HorizontalAlignment="Left" Margin="64,8,0,0" Name="txtSearchBox" VerticalAlignment="Top" Width="224" TextChanged="txtSearchBox_TextChanged" /> 
     <TextBlock Text="Search" HorizontalAlignment="Left" Margin="11,12,0,0" Name="label1" VerticalAlignment="Top" Height="23" /> 
    </Grid> 
</UserControl> 

code:

using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

using Tracker.Model; 

namespace Tracker 
{ 
    /// <summary> 
    /// Interaction logic for DocumentsView.xaml 
    /// </summary> 
    public partial class DocumentsView : UserControl 
    { 
     private TrackerDataContext db; 

     public DocumentsView() 
     { 
      InitializeComponent(); 
      this.Loaded += new RoutedEventHandler(DocumentsView_Loaded); 
     } 

     void DocumentsView_Loaded(object sender, RoutedEventArgs e) 
     { 
      db = new TrackerDataContext(); 
      dataGrid1.ItemsSource = db.Documents; 
     } 

     private void txtSearchBox_TextChanged(object sender, TextChangedEventArgs e) 
     { 
      TextBox textbox = sender as TextBox; 
      if (textbox != null) 
      { 
       string searchstr = textbox.Text; 
       if (!string.IsNullOrEmpty(searchstr)) 
       { 
        var filtered = from document in db.Documents 
            where document.Subject.Contains(searchstr) 
             || document.Reference.Contains(searchstr) 
            select document; 

        dataGrid1.ItemsSource = filtered; 
       } 
       else 
       { 
        dataGrid1.ItemsSource = db.Documents; 
       } 
      } 
     } 
    } 
} 

Répondre

5

Je pense que vous devez charger tout l'enregistrement de la base de données au début et ensuite utiliser ICollectionView.Filter sur le ItemsSource. Alors vous ne serez pas avoir à faire transaction de base de données

Vous devez wrtie quelque chose comme ça

private void txtSearchBox_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     TextBox textbox = sender as TextBox; 
     if (textbox != null) 
     { 
      _searchstr = textbox.Text; 
      if (!string.IsNullOrEmpty(_searchstr)) 
      { 
       ICollectionView view = CollectionViewSource.GetDefaultView(ItemsSource); 
       view.Filter = new Predicate<object>(filter); 
      } 
     } 
    } 

    private bool filter(object item) 
    { 
     if(item.Subject.Contains(_searchstr) || item.Reference.Contains(searchstr)) 
     { 
      return true; 
     } 
     return false;   
    } 

Hope this helps, Nidal.

+0

Merci merci! :-) – tommed

+0

Petite correction, il vous suffit de vérifier la valeur NULL dans le _searchStr, sinon, une fois que vous commencez à supprimer les caractères recherchés, la liste ne revient pas. – sonne