DataGridView - одновременный ввод и вывод - это ошибка в DataGridView - PullRequest
5 голосов
/ 22 декабря 2009

Я создал приложение C # для Windows Forms, которое я постарался сделать максимально простым, чтобы продемонстрировать проблему, с которой сталкиваюсь. Я пытаюсь использовать DataGridView, чтобы разрешить ввод данных пользователем в одном столбце и одновременно получать обновления в другом столбце из фонового потока.

Проблема в том, что столбец «Входные данные» практически недоступен для редактирования, поскольку, я думаю, обновления, предназначенные для столбца «Выходные данные», приводят к тому, что столбец «Входные данные» обновляется в соответствии с его текущим значением, пока пользователь пытается изменить его. .

Это ошибка в DataGridView? Есть ли лучший способ сделать это? Кто-нибудь может порекомендовать хороший обходной путь?

Следующий код демонстрирует проблему. Столбец «Выход» будет постоянно обновляться, а столбец «Ввод» практически недоступен для редактирования. Я объединил код конструктора (Form1.designer.cs) и Main (из Program.cs) в код формы (Form1.cs), поэтому следующий код должен работать сам по себе.

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Timers;

public partial class Form1 : Form
{
    private System.ComponentModel.IContainer components = null;

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.dataGridView = new System.Windows.Forms.DataGridView();
        ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
        this.SuspendLayout();
        // 
        // dataGridView
        // 
        this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
        this.dataGridView.Location = new System.Drawing.Point(3, 12);
        this.dataGridView.Name = "dataGridView";
        this.dataGridView.RowTemplate.Height = 24;
        this.dataGridView.Size = new System.Drawing.Size(322, 158);
        this.dataGridView.TabIndex = 0;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(328, 174);
        this.Controls.Add(this.dataGridView);
        this.Name = "Form1";
        this.Text = "Form1";
        this.Load += new System.EventHandler(this.Form1_Load);
        ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.DataGridView dataGridView;

    public Form1()
    {
        InitializeComponent();
    }

    BindingSource bindingSource = new BindingSource();
    BindingList<Item> items = new BindingList<Item>();
    private System.Timers.Timer timer;
    private void Form1_Load(object sender, EventArgs e)
    {
        dataGridView.DataSource = bindingSource;
        bindingSource.DataSource = items;
        items.Add(new Item(dataGridView));

        timer = new System.Timers.Timer {Interval = 50};
        timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        timer.Start();
    }

    private Random random = new Random();
    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        items[0].SetOutput(random.Next(100));
    }
}


class Item : INotifyPropertyChanged
{
    public int Input { get; set; }

    private int output;
    public int Output
    {
        get { return output; }
        private set
        {
            output = value;
            OnPropertyChanged("Output");
        }
    }

    public Control control;

    public Item(Control control)
    {
        this.control = control;
    }

    public void SetOutput(int outputValue)
    {
        Output = outputValue;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            if(!control.IsDisposed)
                control.BeginInvoke(handler, this, new PropertyChangedEventArgs(name));
        }
    }
}

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

Ответы [ 3 ]

1 голос
/ 22 декабря 2009

Я подозреваю, что когда происходит событие PropertyChanged, DataGridView обновляет все ячейки или, возможно, только ячейки в измененной строке (это происходит при редактировании другой строки?), Теряя все незафиксированные изменения.

Если вы можете перехватить событие до того, как DataGridView обновит ячейки, вы можете сохранить незафиксированные изменения, чтобы восстановить их после обновления. Но это был бы уродливый обходной путь ...

Вы спрашивали на форумах MSDN? Может быть, кто-то из MS мог бы дать вам более полезный ответ

0 голосов
/ 29 марта 2015

попытаться обновить столбец не за 50 миллисекунд, а с интервалом, равным 4000 его работа для меня может изменить значение в другом столбце и все равно получить изменение в другом столбце

0 голосов
/ 22 декабря 2009

Может быть, редактируемая ячейка теряет фокус? Возможно, каждый раз, когда вы обновляете другой столбец, сохраняете место редактирования и сбрасываете фокус после обновления?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...