防止DataGridView BindingSource更新特定列的单元格值

时间:2019-03-21 19:29:44

标签: vb.net winforms datagridview datatable bindingsource

我有一个DataGridView使用DataTable绑定到BindingSource,并且DataGridView中的所有列都不都绑定到该DataSource的属性。更具体地说,我有一个自定义DataGridViewColumn的自定义DataGridViewCheckBoxColumn派生自DataTable.AcceptChanges类,并具有一个主复选框,该复选框控制列标题中的其他复选框。我的问题是,每当调用DataGridViewCheckBoxCell时,DataTable.AcceptChanges都会恢复为默认值(False),而我失去了先前的选择。有谁知道防止或避免这种行为的好方法?

从本质上讲,即使在调用Ctrl+S之后,我仍然希望保留该列中的单元格值,因为它们与基础数据源无关。

这是一些示例代码,可重现我的经验。选中选择列中的某些复选框,然后按DataGridViewColumn,请注意,即使它们未绑定到特定的BindingSource,您也会每次都丢失它们。我意识到这可能是AcceptChanges的本质,但是我想知道是否有解决此问题的方法。另外,我想避免编写逻辑来保存在调用AcceptChanges之前选择了哪些行,然后在DataGridView返回之后将其重置的逻辑。对我来说,如果一次在Public Class Form1 Sub New() InitializeComponent() Dim dgv As New DataGridView dgv.Columns.Add(New DataGridViewCheckBoxColumn With {.HeaderText = "Selection"}) dgv.Columns.Add(New DataGridViewTextBoxColumn With {.HeaderText = "ChangeMe", .DataPropertyName = "ChangeMe"}) Controls.Add(dgv) : dgv.Dock = DockStyle.Fill Dim dt = New DataTable : dt.Columns.Add("ChangeMe", GetType(String)) For Each thing In {"Shoe", "Boat", "Rat"} : dt.Rows.Add(thing) : Next dgv.DataSource = New BindingSource(dt, Nothing) Me.KeyPreview = True AddHandler Me.KeyDown, Sub(sender As Object, e As KeyEventArgs) If e.Control AndAlso e.KeyCode = Keys.S Then dt.AcceptChanges() End Sub End Sub End Class 中选择了很多行,这似乎太麻烦了。有人有一个更骇人听闻的主意吗?

public class SumatraWrapper : IDisposable
{
    private readonly FileInfo _tempFileForExe = null;
    private readonly FileInfo _exe = null;

    public SumatraWrapper()
    {
        _exe = ExtractExe();
    }

    public SumatraWrapper(FileInfo tempFileForExe)
        : this()
    {
        _tempFileForExe = tempFileForExe ?? throw new ArgumentNullException(nameof(tempFileForExe));
    }

    private FileInfo ExtractExe()
    {
        string tempfile = 
            _tempFileForExe != null ? 
            _tempFileForExe.FullName : 
            Path.GetTempFileName() + ".exe";

        FileInfo exe = new FileInfo(tempfile);
        byte[] bytes = Properties.Resources.SumatraPDF;

        using (FileStream fs = exe.OpenWrite())
        {
            fs.Write(bytes, 0, bytes.Length);
        }

        return exe;
    }

    public bool Print(FileInfo file, string printerName)
    {
        string arguments = $"-print-to \"{printerName}\" \"{file.FullName}\"";
        ProcessStartInfo processStartInfo = new ProcessStartInfo(_exe.FullName, arguments)
        {
            CreateNoWindow = true
        };
        using (Process process = Process.Start(processStartInfo))
        {
            process.WaitForExit();
            return process.ExitCode == 0;
        }
    }

    #region IDisposable Support
    private bool disposedValue = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.
            try
            {
                File.Delete(_exe.FullName);
            }
            catch
            {

            }

            disposedValue = true;
        }
    }

    // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
    // ~PdfToPrinterWrapper() {
    //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
    //   Dispose(false);
    // }

    // This code added to correctly implement the disposable pattern.
    public void Dispose()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
        // TODO: uncomment the following line if the finalizer is overridden above.
        // GC.SuppressFinalize(this);
    }
    #endregion
}

1 个答案:

答案 0 :(得分:0)

此问题是由port 9000,响应于BindingSource方法而引发类型为ListChangedType.Reset的{​​{3}}引起的。 DataTable.AcceptChanges收到此事件后,将从DataGridView重新加载,这在BindingSource.ListChanged Event中发生(向下滚动到第658行)。

一种可能的解决方法是通过修改以下密钥处理程序方法来防止BindingSource.在执行BindingSource期间引发事件。

DataTable.AcceptChanges