【问题标题】:How to refresh a DataGrid that has been populated by a DataProvider every 1min如何每 1 分钟刷新一次由 DataProvider 填充的 DataGrid
【发布时间】:2017-12-15 05:23:03
【问题描述】:

我有以下xaml,您可以看到DataGrids 正在通过DataProviders 填充。

<Window x:Class="MobileDeviceAuthenticator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MobileDeviceAuthenticator"
        Title="Device Authorization" Height="381" Width="879" AllowDrop="True">
    <Window.Resources>
        <!-- create an instance of our DataProvider class -->
        <ObjectDataProvider x:Key="MobileManagerDataProvider" ObjectType="{x:Type local:MobileManagerDataProvider}"/>
        <!-- define the method which is invoked to obtain our data -->
        <ObjectDataProvider x:Key="MOBILE_MANAGER" ObjectInstance="{StaticResource MobileManagerDataProvider}" MethodName="GetDevices"/>
        <!-- create an instance of our DataProvider class -->
        <ObjectDataProvider x:Key="MobileRequestDataProvider" ObjectType="{x:Type local:MobileRequestDataProvider}"/>
        <!-- define the method which is invoked to obtain our data -->
        <ObjectDataProvider x:Key="MOBILE_REQUESTS" ObjectInstance="{StaticResource MobileRequestDataProvider}" MethodName="GetDevices"/>
    </Window.Resources>
    <Grid Name="GridContainer" >
        <Grid>
            <DataGrid Name="dgAuthorization" 
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch" 
                      DataContext="{Binding Source={StaticResource MOBILE_MANAGER}}" 
                      ItemsSource="{Binding}" 
                      AutoGenerateColumns="False" >
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding Path=DESCRIPTION}" Header="Description" />
                    <DataGridTextColumn Binding="{Binding Path=DEVICE_TYPE}" Header="Device Type" IsReadOnly="True" />
                    <DataGridTextColumn Binding="{Binding Path=DEVICE_ID}" Header="Device ID" IsReadOnly="True" />
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
        <Grid>
            <DataGrid Name="dgRequest" 
                      SelectionMode="Single" 
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch"
                      DataContext="{Binding Source={StaticResource MOBILE_REQUESTS}}"
                      ItemsSource="{Binding}"  
                      AutoGenerateColumns="False" >
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding Path=DESCRIPTION}" Header="Description" />
                    <DataGridTextColumn Binding="{Binding Path=DEVICE_TYPE}" Header="Device Type" IsReadOnly="True" />
                    <DataGridTextColumn Binding="{Binding Path=DEVICE_ID}" Header="Device ID" IsReadOnly="True" />
                    <DataGridTextColumn Binding="{Binding Path=REQUEST_DATE}" Header="Request Date" />
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Grid>
</Window>

这是DataProvider类代码

public class MobileManagerDataProvider
{
    private MobileManagerDataSetTableAdapters.MOBILE_MANAGERTableAdapter mmAdapter;
    private MobileManagerDataSet mmDataSet;

    public MobileManagerDataProvider()
    {
        mmDataSet = new MobileManagerDataSet();
        mmAdapter = new MobileManagerDataSetTableAdapters.MOBILE_MANAGERTableAdapter();
        mmAdapter.Fill(mmDataSet.MOBILE_MANAGER);

        mmDataSet.MOBILE_MANAGER.MOBILE_MANAGERRowChanged += new MobileManagerDataSet.MOBILE_MANAGERRowChangeEventHandler(AuthenticationRowModified);
        mmDataSet.MOBILE_MANAGER.MOBILE_MANAGERRowDeleted += new MobileManagerDataSet.MOBILE_MANAGERRowChangeEventHandler(AuthenticationRowModified);
    }

    public DataView GetDevices()
    {
        return mmDataSet.MOBILE_MANAGER.DefaultView;
    }

    void AuthenticationRowModified(object sender, MobileManagerDataSet.MOBILE_MANAGERRowChangeEvent e)
    {
        mmAdapter.Update(mmDataSet.MOBILE_MANAGER);
    }
}

在代码隐藏中,我想设置一个Timer,每分钟刷新一次DataGrids

Timer 很简单,但是刷新数据让我望而却步。我尝试了以下一些说法。

ObjectDataProvider dataProvider = this.TryFindResource("MobileManagerDataProvider") as ObjectDataProvider;
dataProvider.Refresh();

dgAuthorization.Items.Refresh();

CollectionViewSource.GetDefaultView(dgAuthorization.ItemsSource).Refresh();

无济于事,我怎样才能做到这一点?

【问题讨论】:

  • 如果你创建 'ObservableCollection' 对象并将其绑定到 DataGrid,它将在 DataGrid 中自动更新。
  • 您能否提供一个示例,说明我如何将其实施到我的项目中
  • 我问的原因是我的更新等是通过 DataProvider 发生的,并且必须反映在 ObservableCollection 中。所以我想知道我是如何将它们拼凑在一起的。
  • 我假设您正在获取 DataSet 中的数据,因此您可以使用 foreach 或 for 循环将其复制到 ObservableCollection
  • 我回复了一个示例,每次您在其中选择一个项目时将新数据绑定到 DataGrid,您可以扩展该案例,以便每次您的集合更改时它都会自动反映在您的 DataGrid 中

标签: c# wpf datagrid objectdataprovider


【解决方案1】:

这是一个完整的工作示例,每次您选择一个项目(不是两次相同的项目)时,它都会在DataGrid 中添加一个新的随机值作为新行

我已经回复了一个将新数据绑定到 DataGrid 的示例,每次您在其中选择一个项目时,您都可以扩展该案例,因此每次您的集合更改时,它都会自动反映在您的 DataGrid 中,因此,每当您的数据更改时,您只需传递给GridData 属性,它们就会在视图中更新

MainWindow.xaml

<Window x:Class="BindingDataGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:BindingDataGrid"
        Title="MainWindow" Height="350" Width="525">

        <Window.DataContext>
            <local:MainViewModel />
        </Window.DataContext>
    <Grid>
        <DataGrid  ColumnWidth="*" 
                    IsReadOnly="True"
                    AutoGenerateColumns="False"
                    SelectionMode="Single" 
                    HorizontalContentAlignment="Center" 
                    ItemsSource="{Binding GridData}"
                    SelectedItem="{Binding SelectedData, UpdateSourceTrigger=PropertyChanged}"
                    CanUserResizeRows="False"
                    ScrollViewer.CanContentScroll="True"
                    ScrollViewer.VerticalScrollBarVisibility="Auto"
                    ScrollViewer.HorizontalScrollBarVisibility="Auto">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Column 01" Binding="{Binding Column1}"   Width="*"/>
                <DataGridTextColumn Header="Column 02" Binding="{Binding Column2}"   Width="*"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

MainWindow.xaml.cs这里什么都没有,只是删除未使用的引用

using System.Windows;

namespace BindingDataGrid  //`BindingDataGrid` is my namespace
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

您需要的所有参考资料在您的MainViewModel

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;

MainViewModel

public class MainViewModel: INotifyPropertyChanged
{
    Random _rnd = new Random();
    private MyGridData _selectedData;
    private ObservableCollection<MyGridData> _gridData;
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public MainViewModel()
    {
        var newData = new List<MyGridData>
        {
            new MyGridData { Column1 = "AAAAAA 01", Column2 = "aaaaaaaa 02" },
            new MyGridData { Column1 = "BBBBBB 01", Column2 = "bbbbbbbb 02" },
            new MyGridData { Column1 = "CCCCCC 01", Column2 = "cccccccc 02" },
        };
        GridData = new ObservableCollection<MyGridData>(newData);
    }

    public MyGridData SelectedData
    {
        get { return _selectedData; }
        set
        {
            if (value == _selectedData) //if same item selected
                return;
            _selectedData = value;
            OnPropertyChanged();

            DoSomethingWhenValueChanged(); // Will add a new line
        }
    }
    public ObservableCollection<MyGridData> GridData
    {
        get { return _gridData; }
        set
        {
            if (value == _gridData)
                return;
            _gridData = value;
            OnPropertyChanged();
        }
    }

    private void DoSomethingWhenValueChanged()
    {
        var newData = GridData.ToList();
        newData.Add(new MyGridData { Column1 = (_rnd.Next(100)).ToString(), Column2 = (_rnd.Next(1000)).ToString() }); //Add new random item

        GridData = new ObservableCollection<MyGridData>(newData);  //update your DataGrid
    }
}

public class MyGridData
{
    public string Column1 { get; set; }
    public string Column2 { get; set; }
}

【讨论】:

  • [PropertyChanged?.Invoke] 设计时间在这部分有错误。
  • 我是否用“if (PropertyChanged != null)”把它括起来并删除问号?
  • 但是,就视图和视图模型以及填充 ObservableCollection 而言,这是可以理解的。我现在难以理解的是,如何识别何时添加、删除或更新行,我通过调用 GetDevices() 填充 OC 并复制每个 DataRowView,当我选择一行时,编辑列然后选择它通过 DataProvider 自动更新一个新行,它曾经自动执行此操作以添加或删除一行。事实上,即使 CanUserAddRows=True,添加行也消失了。我现在该如何完成?
  • “我是否用“if (PropertyChanged != null)”包围它并删除问号?是的。这是 C# 版本 6
  • 在这里你可以看到如何使用 MVVM 添加行 - stackoverflow.com/q/20195808/5605739
猜你喜欢
  • 2011-08-28
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多