如何创建动态WPF数据网格?

时间:2012-11-27 08:08:43

标签: c# wpf linq datagrid

我有一个动态数据库,数据库中的数据将在一分钟内更新。现在,我在我的WPF项目中创建了一个datagrid,我想显示数据库中的所有数据。当我运行我的项目时,datagrid将只显示静态数据(项目运行之前的数据)。如何确保我的数据网格在运行后保持自我更新?顺便说一句,我使用linq to sql和C#作为我的WPF项目。

我的数据网格的代码段:

<DataGrid AutoGenerateColumns="False" Name="MyDataGrid" VerticalAlignment="Top" Width="185" >
     <DataGrid.Columns>
          <DataGridTextColumn Header="Date"  Width="60" Binding="{Binding Date}" />
          <DataGridTextColumn Header="Time" Width="55" Binding="{Binding Time}"/>
          <DataGridTextColumn Header="Id" Width="69" Binding="{Binding id}" />
    </DataGrid.Columns>
</DataGrid>

我的代码背后的代码段:

public  MainWindow()
{
        InitializeComponent();

        using (MyDummyDataContext db = new MyDummyDataContext())
        {
            var query = from p in db.Ids
                        orderby p.Id descending
                        select new 
                        { 
                            Date = p.Date,
                            Time = p.Time,
                            id = p.Id
                        };
            MyDataGrid.ItemsSource = query;
        }
}

1 个答案:

答案 0 :(得分:1)

这是我的2美分:

  1. 将您的DataGird的ItemsSource绑定到ObservableCollection。
  2. 在加载的事件处理程序上初始化集合。
  3. 添加计时器,在计时器的回调中,您可以从数据库刷新集合。注意:如果您使用的是.NET 4.5,则支持更新ObservableCollection表单后台线程。否则,您需要手动处理线程同步。
  4. 以下是在后台更新数据的链接,可能不完全适合您的问题,但您可以获得一些想法:

    Observable Collection Cross-Thread Change Notification

    编辑:

    我刚刚编写了一个示例(为简单起见,我使用DispatcherTimer来更新UI线程中的集合。要在后台线程中更新数据,您需要使用System.Timers.Timer,并使用链接中的方法。) :

    App.xaml.cs:

    using System.Windows;
    
    namespace DataGridTest
    {
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            var vm = new MainWindowViewModel();
            var mainWindow = new MainWindow { DataContext = vm };
            mainWindow.Show();
        }
    }
    }
    

    MainWindow.xaml

    <Window x:Class="DataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid AutoGenerateColumns="False" Name="MyDataGrid" VerticalAlignment="Top" Width="185"
                  ItemsSource="{Binding Persons}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id"  Width="60" Binding="{Binding Id}" />
                <DataGridTextColumn Header="Name" Width="55" Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
    

    MainWindow.cs:

    using System.Windows;
    
    namespace DataGridTest
    {
    using System;
    using System.ComponentModel;
    using System.Windows.Threading;
    
    public class Person : INotifyPropertyChanged
    {
        private int _id;
    
        private string _name;
    
        public int Id
        {
            get
            {
                return _id;
            }
    
            set
            {
                if (this._id == value)
                    return;
    
                this._id = value;
                this.OnPropertyChanged("Id");
            }
        }
        public string Name
        {
            get
            {
                return _name;
            }
    
            set
            {
                if (this._name == value)
                    return;
    
                this._name = value;
                this.OnPropertyChanged("Name");
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly DispatcherTimer _timer = new DispatcherTimer();
    
        public MainWindow()
        {
            InitializeComponent();
    
            _timer.Interval = TimeSpan.FromSeconds(1);
            _timer.Tick += this._timer_Tick;
            _timer.Start();
        }
    
        private void _timer_Tick(object sender, EventArgs e)
        {
            var vm = this.DataContext as MainWindowViewModel;
            if(vm != null)
                vm.Refresh();
        }
    }
    }
    

    MainWindowViewModel.cs

    namespace DataGridTest
    {
      using System.Collections.ObjectModel;
      using System.ComponentModel;
    
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        private readonly ObservableCollection<Person> _persons = new ObservableCollection<Person>();
    
        private static int _id = 3;
    
        public ObservableCollection<Person> Persons
        {
            get
            {
                return _persons;
            }
        }
    
        public MainWindowViewModel()
        {
            _persons.Add(new Person { Id = 1, Name = "A" });
            _persons.Add(new Person { Id = 2, Name = "B" });
            _persons.Add(new Person { Id = 3, Name = "C" });  
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        public void Refresh()
        {
            _persons.Add(new Person() { Id = ++_id, Name = _id.ToString() });
        }
    
    }
    

    }