views:

35

answers:

1

Hi guys,

I have a WPF application which uses a (currently) local database to act as a binding source. Using the Visual Studio 2010 tools I have a LINQ-SQL model which acts as the Datacontext for most forms.

What I have is a UserControl with a TextBox and Datagrid. The datagrid ItemSource is set upon the UserControl.Loaded event with a table. The TextBox has an event assigned so that a query is executed upon the database when the text changes and the ItemSource is updated upon the datagrid.

The problem with this is the time it takes to query the database. As I'm reassigning the DataGrid itemsource for each search.

  1. Should I be loading all records upon the UserControl Loading - is there a way to load records asynchronously in a BackgroundWorker or similar?

  2. Do I need to reassign the DataGrid ItemsSource after each search or is their a more efficient way to filter the data?

Thanks. 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;
                }
            }
        }
    }
}
A: 

I think you should load all the record from the database at the begining and then use ICollectionView.Filter on the ItemsSource. So then you will not have to do data base transaction

You should wrtie something like that

    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.

Nidal Valot