WPF 数据绑定数据网格过滤/搜索

发布于 2024-09-10 15:25:03 字数 3419 浏览 6 评论 0原文

我有一个 WPF 应用程序,它使用(当前)本地数据库作为绑定源。使用 Visual Studio 2010 工具,我有一个 LINQ-SQL 模型,它充当大多数表单的数据上下文。

我拥有的是带有文本框和数据网格的用户控件。数据网格 ItemSource 是根据 UserControl.Loaded 事件和表设置的。 TextBox 分配了一个事件,以便当文本更改并且 ItemSource 在数据网格上更新时对数据库执行查询。

这样做的问题是查询数据库所需的时间。当我为每个搜索重新分配 DataGrid itemsource 时。

  1. 我是否应该在 UserControl 加载时加载所有记录 - 有没有办法在 BackgroundWorker 或类似的中异步加载记录?

  2. 我是否需要在每次搜索后重新分配 DataGrid ItemsSource,或者它们是过滤数据的更有效方法吗?

谢谢。 利亚姆

<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>

代码:

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;
                }
            }
        }
    }
}

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;
                }
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

摘星┃星的人 2024-09-17 15:25:03

我认为你应该一开始就从数据库加载所有记录
然后在 ItemsSource 上使用 ICollectionView.Filter。
那么你就不必进行数据库事务

你应该写类似的东西

    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;           
    }

希望这会有所帮助,
尼达尔。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文