开发者

Help with auto populating cells contents into a new window

What I looking to do is, when开发者_如何学C a user double clicks on a cell in the datagrid, a new window opens and the cells contents are auto populated into that window so that they can be edited. Can anyone help me with this? Thanks.


A naive way to handle this would be to create the form directly inside the dbl-click event from the grid and set the various field by hand, show it, get the new value and update the grid.

While this will work, it is probably a bad idea to do too much directly into a form event handler... Try separating your logic and domain-model from your form.

However this can give you a starting point...

var form = new CellEditingForm();
form.Field1.Text = cellValue;
form.ShowDialog();
string newValue = form.Field1.Text;
// update the grid here...


This looks like something a PropertyGrid could handle very well.

This might help get you started: Getting the Most Out of the .NET Framework PropertyGrid Control


Below is a very crude demonstration of how to create an editable form given only a DataRow. It uses Windows Forms, but it's likely you have a DataRow no matter which framework you're using. If you don't, you can extrapolate.

What this demonstrates is how to dynamically create a form with a bunch of controls. It does provide a rudamentary method to read back the data after the user has messed with it.

What it doesn't do is give you any guidence about how to validate and save the data that has been changed by the user. I'll give you a hint: Attach the DataRow to the form, use binding on the TextBoxes, and use the built-in ErrorProvider features. That way the row becomes dirtied and whatever mechanism you're using to read/write back (i.e. TableAdapter) will gracefully handle it.

I didn't do all of that because it's dependent on what framework you use. This is just a simple example to get you started. If you have specific questions on where to go from here, ask a new and specific question.

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

class DemoForm : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new DemoForm());
    }

    public DemoForm()
    {
        DataTable dataTable = new DataTable { Columns = { "First", "Second", "Third" } };
        dataTable.Rows.Add("This", "Is", "Data");
        dataTable.Rows.Add("Some", "More", "Values");
        DataGridView dgv = new DataGridView
        {
            Dock = DockStyle.Fill,
            DataSource = dataTable,
            RowHeadersVisible = false,
            SelectionMode = DataGridViewSelectionMode.FullRowSelect,
            ReadOnly = true,
        };
        dgv.DoubleClick += (s, e) =>
            {
                if (dgv.SelectedRows.Count > 0)
                {
                    DataRow dataRow = (dgv.SelectedRows[0].DataBoundItem as DataRowView).Row;
                    using (GenericDataRowForm form = new GenericDataRowForm(dataRow))
                    {
                        if (form.ShowDialog(this) == DialogResult.OK)
                        {
                            // TODO: Validate and save data

                            // Just showing how to iterate GenericDataRowForm.Items
                            foreach (KeyValuePair<string, string> pair in form.Items)
                                Trace.WriteLine(String.Format("Column = {0}, Value = {1}", pair.Key, pair.Value));
                        }
                    }
                }
            };
        Controls.Add(dgv);
    }
}

class GenericDataRowForm : Form
{
    public GenericDataRowForm()
    {
    }
    public GenericDataRowForm(DataRow row)
    {
        // Basic dialog box styles
        FormBorderStyle = FormBorderStyle.FixedDialog;
        MinimizeBox = MaximizeBox = ShowInTaskbar = false;
        StartPosition = FormStartPosition.CenterParent;

        // You would probably want to set the caption (this.Text) to
        //  something meaningful from the outside, so left it out here.

        // Record the number of items
        itemCount = row.Table.Columns.Count;

        // Create a TableLayoutPanel to arrange the Label/TextBox pairs (and the Ok/Cancel buttons).
        TableLayoutPanel panel = new TableLayoutPanel
        {
            Name = "LayoutPanel",
            ColumnCount = 2,
            ColumnStyles = { new ColumnStyle(), new ColumnStyle(SizeType.Percent, 100F) },
            RowCount = itemCount + 1,
            // We will dock it later, but we want to know how big it should be.
            AutoSize = true,
        };

        int itemIndex = 0; // Intentionally declared outside as we'll use it for the buttons below.
        for (; itemIndex < itemCount; itemIndex++)
        {
            panel.RowStyles.Add(new RowStyle());
            string columnName = row.Table.Columns[itemIndex].ColumnName;
            panel.Controls.Add(new Label { Text = columnName, AutoSize = true, Anchor = AnchorStyles.Right }, 0, itemIndex);
            // Note that the text box has its Name set to the data column name and it's Text to the value of that column.
            panel.Controls.Add(new TextBox { Name = columnName, Text = row[itemIndex].ToString(), Dock = DockStyle.Fill }, 1, itemIndex);
        }

        // Add Ok and Cancel buttons
        panel.RowStyles.Add(new RowStyle());
        panel.Controls.Add(new Button { Text = "Ok", Name = "OkButton", DialogResult = DialogResult.OK }, 0, itemIndex);
        panel.Controls.Add(new Button { Text = "Cancel", Name = "CancelButton", DialogResult = DialogResult.Cancel }, 1, itemIndex);
        AcceptButton = panel.Controls["OkButton"] as IButtonControl;
        CancelButton = panel.Controls["CancelButton"] as IButtonControl;

        // Adjust this Form's size to the panel.
        ClientSize = new Size(320, panel.Height + 10);
        // Then dock the panel so that it conforms to the Form.
        panel.Dock = DockStyle.Fill;

        Controls.Add(panel);
    }

    public int ItemCount
    {
        get { return itemCount; }
    }

    // We need some way for the outside world to view the data that
    //  might have been edited by the user. This could be much more
    //  complicated. As a simple example, this allows the consumer
    //  to iterate over each item as a KeyValuePair. The key is the
    //  data column name and the value is the Text field of the TextBox.
    public IEnumerable<KeyValuePair<string, string>> Items
    {
        get
        {
            if (itemCount > 0)
            {
                TableLayoutPanel panel = Controls["LayoutPanel"] as TableLayoutPanel;
                foreach (Control control in panel.Controls)
                {
                    TextBox textBox = control as TextBox;
                    if (textBox != null)
                        yield return new KeyValuePair<string, string>(textBox.Name, textBox.Text);
                }
            }
        }
    }

    private int itemCount = 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜