DataGrid在其ItemSource更新时不会创建Rows&有时重复条目

时间:2018-05-18 06:55:13

标签: c# wpf datagrid wpfdatagrid cross-thread

我们正在制作一个WPF应用程序,它使用FileSystemWatcher监视用户选择目录的更改,并将更改输出到DataGrid。 在我的MainWindow()构造函数中,我将DataGrid绑定到List,我通过ItemSource调用_eventList。

当OnChanged或OnRenamed FileSystemWatcher事件发生时,我的应用程序成功地将四组字符串(更改类型,受影响的文件,路径,最后修改日期)写入我调用的数组_event。这构成了一件事。然后,在创建了这个_event数组后,我做了一个苍白的尝试来处理我的“调用线程无法访问此对象,因为另一个线程拥有它”,通过调用一个名为SetThreadSafe()的单独方法来交叉线程异常。 p>

这是我相信事情让我失望的地方。我的SetThreadSafe方法中发生的不需要的行为是我的DataGrid显示它包含在其Items属性中,每个事件对应的条目。 DataGrid.Items中的每个索引都绑定到我的_eventList(应该如此)的同义词,并且此List / Items属性的每个索引内部都是数组的每个索引中的正确值。

所以,其中一个,我的DataGrid显示它在我的调试器的Items属性中包含正确的数据,但行不会填充在我的DataGrid中。

两个,有时,不是全部,SetThreadSafe方法触发它的IF和它ELSE条件两者,因此在我的DataGrid.Items / _eventList中添加一个重复的条目。我不再获得跨线程异常了,但我觉得这里有一些我很清楚的东西。

[更新:感谢ASh,我的问题得到了解决。我重新编辑了我的代码以反映正确的调整。现在一切都正常。]

C#:

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using WinForms = System.Windows.Forms;

namespace EyeInTheSky
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml + backend code for FileSystemWatcher project
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Fields
        private FileSystemWatcher _watcher;
        private string[] _event;
        private ObservableCollection<string[]> _eventList;
        private bool _on;
        #endregion

        #region class Constructor
        public MainWindow()
        {
            InitializeComponent();
            _eventList = new ObservableCollection<string[]>();
            DataGrid_DisplayOutput.ItemsSource = _eventList;
        }
        #endregion

        #region FileSystemWatcher Methods
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            _event = new string[4];
            _event[0] = e.ChangeType.ToString();
            _event[1] = e.Name;
            _event[2] = e.FullPath;
            _event[3] = DateTime.Now.ToString();

            SetThreadSafe();
        }

        private void OnRenamed(object source, RenamedEventArgs e)
        {
            _event = new string[4];
            _event[0] = e.ChangeType.ToString();
            _event[1] = e.Name;
            _event[2] = e.OldFullPath;
            _event[3] = DateTime.Now.ToString();

            SetThreadSafe();
        }

        private delegate void SetCallback();
        private void SetThreadSafe()
        {
            if (!CheckAccess())
            {
                SetCallback d = new SetCallback(SetThreadSafe);
                Dispatcher.Invoke(d);
            }
            else
            {
                _eventList.Add(_event);
            }
        }
        #endregion

WPF XAML:

<DataGrid x:Name="DataGrid_DisplayOutput" Grid.Column="1" HorizontalAlignment="Left" Margin="22,11,0,0" Grid.RowSpan="4" VerticalAlignment="Top" Width="356" Height="392" IsTextSearchEnabled="True" RowBackground="#FFFFFAE8" AlternatingRowBackground="White" HeadersVisibility="Column" AlternationCount="1" SelectionMode="Single" IsReadOnly="True">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding [0]}" Header="Change" Width="89" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding [1]}" Header="Change" Width="89" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding [2]}" Header="Change" Width="89" IsReadOnly="True"/>
        <DataGridTextColumn Binding="{Binding [3]}" Header="Change" Width="89" IsReadOnly="True"/>
    </DataGrid.Columns>
</DataGrid>

1 个答案:

答案 0 :(得分:0)

代码中有多个地方需要修复

List<string[]>更改为ObservableCollection<string[]>以修复&#34;不会在我的DataGrid中填充行。&#34;问题。与List不同,ObservableCollection 可以在添加/删除项目时通知UI

_event仅在构造函数中创建_event = new string[4];一次。这意味着您只有1个数组并多次添加它并在执行更改/重命名时擦除值。我想您需要在OnChanged / OnRenamed

中创建新数组

没有DataGridTextColumn具有&#34;绑定&#34;属性配置。由于DataGrid中的每一行都显示一个数组,因此Bindings应使用索引:

<DataGridTextColumn Binding="{Binding [0]}" Header="Change" Width="89" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding [1]}" Header="File" Width="89" IsReadOnly="True"/>