有两个winform窗口A,B。A窗口有一个datagridview,点击新增弹出B窗口,在B窗口中输入文本框的值,点保存,把数据插入到A窗口的datagridview中,有几个不懂的地方,窗口之间是如何传递事件的?点击保存要能在A窗口上触发插入事件,这个是如何触发的?datagridview没有绑定数据库,只是做个临时存储数据的作用,等用户全部添加之后,在一次性存到数据库里面,如何不绑定数据库datagridview插入数据呢

解决方案 »

  1.   

    B中定义委托和事件,当B中保存发生后触发事件,A注册B的保存事件
    datagridView以DataTable作为数据源,可在编辑后插入数据到表
    取消保存:dt.RejectChanges(); //DataTable撤销所有更改(行状态均变为UnChanged)
    确认更新数据库:da.Update(dt); //适配器更新数据库中相应表数据为dt表中数据
      

  2.   

    窗口之间传值的标准方法就是用委托
    说一些非标准方法:
    为要传递的数据建立一个结构 TData
    在B窗口里建立一个全局函数:public TData ShowMe()
    函数里:this.ShowDialog(),之后填充TData并返回,A窗口里就可以取得这个值并继续处理了。还可以在B里声明一个全局的A窗体类型的变量,然后在A里new B窗口之后再把A的引用传给那个变量,这样就可以从B里操作A里的东西了。在DataGridView添加行的方法:
    DataGridViewRow row = new DataGridViewRow();
    row.CreateCells(dataGridView1);
    row.Cells[0].Value = "测试";
    datagridview1.Rows.Add(row);
      

  3.   

    winfrom间传值通过公共静态类进行传值; 
    通过绑定事件进行传值; 
    使用Attribute 
    public partial class Form1 : Form 

    private void button1_Click(object sender, EventArgs e) 

    Form2 frm2 = new Form2(); 
    frm2.Show(this); 

    } public partial class Form2 : Form 

    private void button1_Click(object sender, EventArgs e) 

    Form1 frm1 = (Form1)this.Owner; 
    ((TextBox)frm1.Controls["textBox1"]).Text = this.textBox2.Text; 
    this.Close(); 


    还可使用委托 
    使用SqlCommandBuilder更新到数据库
      

  4.   

    方法有很多了
    1,利用第三方类的静态属性,做为中转,Form2启动的时候读取
    2。给Form2窗体再多些几个属性,Form2启动的时候,对其属性付值,Form2内部就可以用了
    3。重载Form2的构造函数,多几个参数入口,到时候传过来就可以了
    4。Form2中定义几个public的变量,也可以,一般不用这个
    5。Form2中的值回传的时候,可以用委托来实现
    总之 方法很多了。。 
      

  5.   

    把值传回来容易,问题是传回来后怎么插入到datagirdview里面,触发什么事件呢
      

  6.   

    窗体的参数传递
    http://blog.csdn.net/zhzuo/archive/2006/05/05/708941.aspx#sec5窗体的参数传递
    对于窗体间的数据传递,是刚开始从事.Net窗体应用程序开发人员碰到的一个常见问题,在此讲几个常见的实现方式。此节内容适用于模式窗体或非模式窗体,部分方式延伸到一般类的操作。(1)构造函数参数传递
    通过构造函数传递参数应该是比较基本的参数传递方式,重载构造函数,通过带参数的构造函数来实例化窗体。
    在窗体类内部定义参数变量,
    private object myParams;实现构造函数,
    public OptionForm(object parameters)
    {
        InitializeComponent();
        this.myParams = parameters;//设置参数引用
    }实例化窗体,
    OptionForm form = new OptionForm( myParams );在实际使用过程中,需要注意传入的是引用类型还是值类型,处理方式会有所不同。(2)使用窗体的属性
    说起属性关联,上面已经提到过Form.Owner属性,下面笔者根据MSDN文档来比较完整的讲一下,大部分的文字来自MSDN文档,为保证其完整性,对其中一些属性描述进行了扩展。Form.Owner 属性。获取或设置拥有此窗体的窗体。
    语法,public Form Owner { get; set; }
    若要使某窗体归另一个窗体所有,可为其 Owner 属性分配一个对将成为所有者的窗体的引用。当一个窗体归另一窗体所有时,它便随着所有者窗体最小化和关闭。例如,如果 Form2 归窗体 Form1 所有,则关闭或最小化 Form1 时,Form2 也会关闭或最小化。并且附属窗体从不显示在其所有者窗体后面。可以将附属窗体用于查找和替换窗口之类的窗口,当选定所有者窗体时,这些窗口不应消失。
    Form.OwnedForms 属性。获取 Form 对象的数组,这些对象表示此窗体拥有的所有窗体。
    语法,public Form[] OwnedForms { get; }
    此属性返回包含此窗体拥有的所有窗体的数组。要使某窗体归另一个窗体所有,可调用 AddOwnedForm 方法。分配给所有者窗体的窗体将保持被拥有状态,直到调用了 RemoveOwnedForm 方法。如果窗体是多文档界面 (MDI) 父窗体,则除了当前打开的所有 MDI 子窗体外,此属性将返回所有显示的窗体。
    Form.MdiChildren 属性。获取窗体的数组,这些窗体表示以此窗体作为父级的多文档界面 (MDI) 子窗体。
    语法,public Form[] MdiChildren { get; }
    此属性使您得以获取对当前在某 MDI 父窗体中打开的所有 MDI 子窗体的引用。若要创建 MDI 子窗体,请将要成为 MDI 父窗体的 Form 分配给该子窗体的 MdiParent 属性。可以使用此属性依次通过所有 MDI 子窗体,以执行一些操作,如当 MDI 父窗体关闭时将数据保存到数据库中,或者根据应用程序中执行的操作更新子窗体上的字段。
    Form.MdiParent 属性。获取或设置此窗体的当前多文档界面 (MDI) 父窗体。
    语法,public Form MdiParent { get; set; }
    若要创建 MDI 子窗体,请将要成为 MDI 父窗体的 Form 分配给该子窗体的 MdiParent 属性。可以从某 MDI 子窗体使用此属性来获取所有子窗体都需要的全局信息或者调用对所有子窗体执行操作的方法。
    Form.ActiveForm 静态属性。获取此应用程序的当前活动窗体。
    语法,public static Form ActiveForm { get; }
    表示当前活动窗体,或者如果没有活动窗体,则为空引用。可以使用此方法获得对当前活动窗体的引用,以在该窗体或其控件上执行操作。
    Form.ActiveMdiChild 属性。获取当前活动的多文档界面 (MDI) 子窗口。
    语法,public Form ActiveMdiChild { get; }
    返回表示当前活动的 MDI 子窗口的 Form,或者如果当前没有子窗口,则返回 空引用。可使用此方法确定 MDI 应用程序中是否有任何打开的 MDI 子窗体。也可使用此方法从 MDI 子窗口的 MDI 父窗体或者从应用程序中显示的其他窗体对该 MDI 子窗口执行操作。
    ContainerControl.ParentForm 属性。获取将容器控件分配给的窗体。
    语法,public Form ParentForm { get; }
    将容器控件分配给的 Form。以上属性MSDN提供相应的代码事例,可直接拿来调试使用。

    (3)使用公共属性
    使用公共属性也是一种比较常用的方式,通过窗体设计器添加的控件默认访问修饰符为private级别,可以设置成public或Internal(在程序集内部可见)来对外公开。比如对窗体中的Button进行公开,那就可以访问Button的相关属性,同时也可以注册事件或撤销事件注册。如,
    OptionForm form = new OptionForm();
    form.buttonOK.Click += new EventHandler(buttonOK_Click);
    form.ShowDialog();对于只允许读取访问或修改访问的控件或变量可以通过属性来控制。对(1)方式进行修改,去除重载构造函数,增加属性也可以实现同样的效果。
    public object MyParams
    {
        get { return this.myParams;  }
        set { this.myParams = value;  }
    }(4)使用公共方法
    使用公共方法类似于属性,对上面的同等实现如下,
    //获取参数
    public object GetParams()
    {
        return this.myParams;
    }
    //设置参数
    public void SetParams(object myParams )
    {
        this.myParams = myParams;
    }(5)使用静态类该方式可以简单的理解为静态变量全局共享
    通过下面代码能够比较清楚的理解,先来定义静态类,
    public static class ParameterSettings
    {
        //公共静态变量
        public static string Username = "Zhengzuo";
        //私有静态变量
        private static string userRole = "Administrators";
        // 私有静态变量
        private static string password = "http://blog.csdn.net/zhzuo";
        //内部属性
        internal static string UserRole
        {
            get { return userRole; }
        }
        //公共属性
        public static string Password
        {
            get { return password; }
            private set { password = value; }
        }
    }在需要访问的地方通过以下方式进行,
    string username = ParameterSettings.Username;
    string password = ParameterSettings.Password;
    string userRole = ParameterSettings.UserRole;
    ParameterSettings.Username = "zhengzuo";//修改成新用户名

    (6)窗体实现 Singleton模式
    Singleton模式是我们开发过程中最常用的模式之一。在技术社区经常看到有人谈及对主窗体实现 Singleton,但个人认为这不是一种妥当的做法,因为没有这个必要。这里通过另一个自定义类来进行演示。假设UserLoginInfo类用来保存登录系统后的用户凭据。
    /*==============================================
    程序 zhzuocn 2006-4-23 http://blog.csdn.net/zhzuo
    ==============================================*/
    public class UserLoginInfo
    {
        //实现Singleton模式,线程安全。
        private readonly static UserLoginInfo currentUserInfo = new UserLoginInfo();
        //提供全局访问点
        public static UserLoginInfo CurrentUserInfo
        {
            get { return currentUserInfo; }
        }
        //阻止显式实例化,但不能阻止反射方式调用。
        private UserLoginInfo()
        {
        }
        //公共变量
        public string Username;
        //私有变量
        private static string userRole;
        //私有变量
        private static string password;
        //内部属性
        internal string UserRole
        {
            get { return userRole; }
            set { userRole = value; }
        }
        //公共属性
        public string Password
        {
            get { return password; }
            internal set { password = value; }
        }
    }在其他代码中进行访问,
    UserLoginInfo.CurrentUserInfo.Username ="zhengzuo";
    UserLoginInfo.CurrentUserInfo.UserRole = "dotnetlover";
    UserLoginInfo.CurrentUserInfo.Password = "http://blog.csdn.net/zhzuo";对于 Singleton模式的实现方式有很多,编写时需要考虑是否需要保证实例访问的线程安全问题,以免引发不可预料的情况,为了提高性能可以考虑惰性实例化。关于Singleton模式的更多信息可以参考另一篇文章。

    (7)发布事件进行订阅
    通过事件来传递参数应该说是一种推的实现方式,在产生事件时进行被动的获取相关数据。这里将通过一个自定义事件来演示数据的传输。
    在自定义事件时,标准的做法都会先定义一个事件参数类,要么直接使用基类EventArgs,或者从EventArgs继承实现自己的参数类,假设自定义基类取名为OptionSettingEventArgs,
    //选项设置事件参数类
    public class OptionSettingEventArgs : EventArgs
    {
        private string changedPath;
        //构造函数
        public OptionSettingEventArgs(string changedPath)
        {
            this.changedPath = changedPath;
        }
        //读取参数
        public string ChangedPath
        {
            get { return this.changedPath; }
        }
    }以上参数类只包含一个修改后的路径参数。接下去我们要对原先的OptionForm窗体增加事件定义,这里使用.net 2.0中提供的泛型类来实现。
    //定义事件
    public event EventHandler<OptionSettingEventArgs> OptionSettingChanged;
    编写事件引发程序如下,
    // 引发OptionSettingChanged事件
    protected virtual void OnOptionSettingChanged(OptionSettingEventArgs e)
    {
        if (OptionSettingChanged != null)
        {
            OptionSettingChanged(this, e);
        }
    }对文件目录选择按钮事件处理程序进行修改来实现事件激发,并没有考虑直接从文本框直接数据输入方式。
    //通过目录对话框设置新的路径
    private void buttonBrowser_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog dialog = new FolderBrowserDialog();
        DialogResult result = dialog.ShowDialog(this);
        if (result == DialogResult.OK)
        {
            if(this.textBoxPath.Text != dialog.SelectedPath)
            {
                this.textBoxPath.Text = dialog.SelectedPath;
                OptionSettingEventArgs args = new OptionSettingEventArgs(dialog.SelectedPath);
                OnOptionSettingChanged(args);
            }
        }
    }好了,一切准备工作完成,调用代码如下,
    OptionForm form = new OptionForm();
    //注册事件
    form.OptionSettingChanged += new EventHandler (form_OptionSettingChanged);
    form.ShowDialog();
    通过以下事件处理程序来验证其正确性,
    private void form_OptionSettingChanged(object sender, OptionSettingEventArgs e)
    {
        string newPath = e.ChangedPath;
        MessageBox.Show(this, String.Format("新路径为“{0}”。", newPath), "提示");

      

  7.   

    重载B窗体的构造函数,通过构造函数将A窗体的datagridview传到B窗体中:
    class B
    {
          public B(datagridview dg)
        {
          InitializeComponent();
           B_dg=dg;
         }
    datagridview B_dg;
    }
       private void button1_Click(object sender, EventArgs e) 
    {
       //在这里将你要向datagridview中添加的东西添加进来,然后在A窗体中就有了你新添加的东东了,
       //要是没有的话,你在新写的B窗体的构造函数的参数前加out,就可以了
    }
    代码不是写的很全,我以前也写过一个类似的,只要把控件传递过来向控件中添加就可以了
      

  8.   

    不知道这个适不适合你用
    1、全局变量
    这个最简单,只要把变量描述成static就可以了,在form2中直接引用form1的变量。Form1中声明一个static变量
    public static int i= 9 ;
    Form2中触发点击事件
    private void button1_Click(object sender, System.EventArgs e)
    {
    textBox1.Text = Form1.i.ToString();
    }2、父窗口传值给子窗口(Form1为主窗体,Form2为子窗体)
    Form1中的代码
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    private void btnShow_Click(object sender, EventArgs e)
    {
    Form2 form2 = new Form2();
    //父窗体传值给子窗体
    Form1 form1 = new Form1();
    form2.String1 = "成功传值给Form2窗体!";
    form2.SetValue();
    form2.ShowDialog();
    }Form2中的代码
    private string String;public string String1
    {
    get { return String; }
    set { String = value; }
    }
    public void SetValue()
    {
    this.lblText.Text = String1;
    }3、父窗口传值给子窗口(Form1为主窗体,Form2为子窗体)
    Form1中的代码
    private string strValue;
    public string StrValue
    {
    get { return strValue; }
    set { strValue = value; }
    }
    private void btnShow_Click(object sender, EventArgs e)
    {
    Form2 form2 = new Form2();
    //子窗体返回值给父窗体
    form2.Owner = this;;//重要的一步,主要是使Form2的Owner指针指向Form1
    form2.ShowDialog();
    MessageBox.Show(StrValue);//显示返回的值
    }
    Form2中的代码
    private void btnclose_Click(object sender, EventArgs e)
    {
    Form1 form1 = (Form1)this.Owner;//把Form2的父窗口指针赋给lForm1
    form1.StrValue = "子窗体成功返回值给父窗体!";//使用父窗口指针赋值
    this.Close();
    }4、父窗口传值给子窗口(Form1为主窗体,Form2为子窗体)
    其实也是和第三中方法一样的哦
    winform1{};
    winform2{ public winform1 OWF =null; }