none
窗体切换问题 RRS feed

  • 问题

  • 请问大家遇到这种情况怎么处理?

    一个MDI父窗体,上面一排按钮,点击一个按钮,弹出一个子窗体。

    我现在是简简单单的把点击哪个窗体就将哪个窗体的visible=true;

    但是遇到这样一个问题,比如两个子窗体A和B,A中有一个整型变量num,这个num变量在构造窗体A的时候从数据库中获得,然后动态生成num个Textbox。B通过一些操作,改变了数据库中的这个变量,我想在B改变完数据库之后,打开A的时候发生变化,怎么做?

    谢谢

    2010年4月29日 3:16

答案

  • 你好!

    在窗体间传递数据的方法比较多:
    1,在子窗体中自定义一个构造函数,参数类型是主窗体,当要显示子窗体的时候,就用这个构造函数来实例化子窗体,然后把this指针传进去,说起来太抽象了,我大概一写大家应该就明白了:
       public class frmMain:Form
       {
            ...
            frmControl controlForm=new frmControl(this);
            controlForm.Show();
        }

        public class frmControl:Form  //子窗体,用来控制主窗体的某些显示!
        {
             private frmMain mainForm;
             public frmControl(frmMain mainForm)
             {
                  this.mainForm=mainForm;
              }
              private void button1_Click(object sender,EventArgs e)

                   {

                               frmMain.textBox1.Text=this.textBox1.Text;  //把子窗体的文本框值传递给主窗体的文本框!

                   }

         }
    2,我个人感觉上面的方法不是很好,虽然实现起来很简单,只是想改变窗体的标题文本,就把整个主窗体的引用都传递给子窗体,这样的方式不是很幽雅,我们用接口来改进上面的方法,这样可以限制暴露给子窗体的功能,降低窗体之间的耦合度:
       public interface IChangeTitle:
       {
            void ChangeTitle(string title);
        }
       public class frmMain:Form,IChangeTitle
       {
            ...
            frmControl controlForm=new frmControl(this);
            controlForm.Show();
            public void ChangeTitle(string title)
            {
                 this.Text=title;
             }       
        }

        public class frmControl:Form  //子窗体,用来控制主窗体的某些显示!
        {
             private IChangeTitle ichangeTitle;
             public frmControl(IChangeTitle ichangeTitle)
             {
                  this.ichangeTitle=ichangeTitle;
              }
              private void button1_Click(object sender,EventArgs e)

                   {

                               ichangeTitle.ChangeTitle(this.textBox1.Text);  //通过接口来调用方法

                   }

         }
    3,为了进一步降低窗体之间的耦合度,我们可以用委托来实现这个需求:
        public partial class ChildForm : Form
        {
            public delegate void TitleChangedHandler(string title);
            public TitleChangedEventHandler TitleChanged;
            public ChildForm()
            {
                InitializeComponent();
            }

           
            private void btn_Ok_Click(object sender, EventArgs e)
            {           
                if (TitleChanged != null)
                    TitleChanged("Test Title"); //委托调用
               
            }
        }
    主窗体给委托变量赋值就可以了:
        public partial class MainForm : Form
        {
            private ChildForm loginForm = new ChildForm();
            public MainForm()
            {
                InitializeComponent();
                loginForm.TitleChanged = new ChildForm.TitleChangedEventHandler(FormTitleChanged);
            }

            protected void FormTitleChanged(string title)
            {
                this.Text = title;
            }

            private void button1_Click(object sender, EventArgs e)
            {
                loginForm.Show();
            }
        }

    4,也可以在子窗体中定义一个自定义的事件,然后自定义一个事件参数,用来传递你想传递的一些信息:
        public partial class ChildForm : Form
        {
            public class TitleChangedEventArgs : EventArgs //事件参数类
            {
                private string title = "";
                public string Title
                {
                    get
                    {
                        return title;
                    }
                    set
                    {
                        title = value;
                    }
                }
            }
            public delegate void TitleChangedEventHandler(object sender, TitleChangedEventArgs e);
            public event TitleChangedEventHandler TitleChanged;
            public ChildForm()
            {
                InitializeComponent();
            }

           
            private void btn_Ok_Click(object sender, EventArgs e)
            {
                TitleChangedEventArgs e1=new TitleChangedEventArgs();
                e1.Title="Login sucessed";
                OnTitleChanged(e1);//触发事件
               
            }

            protected virtual void OnTitleChanged(TitleChangedEventArgs e)   //触发事件的方法
            {
                if (TitleChanged != null)
                    TitleChanged(this, e);
            }
        }

    主窗体订阅这个事件就可以了:
        public partial class MainForm : Form
        {
            private ChildForm loginForm = new ChildForm();
            public MainForm()
            {
                InitializeComponent();
                loginForm.TitleChanged += new ChildForm.TitleChangedEventHandler(FormTitleChanged);
            }

            protected void FormTitleChanged(object sender, ChildForm.TitleChangedEventArgs e)
            {
                this.Text = e.Title;
            }

            private void button1_Click(object sender, EventArgs e)
            {
                loginForm.Show();
            }
        }


    周雪峰
    2010年5月5日 11:46
    版主
  • 你好!

         当Visible属性改变的时候会触发VisibleChanged事件,尝试在这个事件处理程序中重新获取一下num,应该可以解决这个问题!

         希望对你有帮助!


    周雪峰
    2010年4月29日 11:57
    版主

全部回复

  • 谢谢您的回答,但我的问题就是,我每次显示哪个子窗体,就是将其visible=true,不显示时将visible=false,这样的话,每次显示窗体就不会构造窗体,我不知道你听明白我的意思了吗

    2010年4月29日 5:19
  • 在窗体 A 上定义一个委托,然后一个 Timer,一个比较山寨的做法就是用 Timer 定时去查数据库更新了没有,更新了,调委托重新画 TextBox。
    Mark Zhou
    2010年4月29日 9:58
  • 你好!

         当Visible属性改变的时候会触发VisibleChanged事件,尝试在这个事件处理程序中重新获取一下num,应该可以解决这个问题!

         希望对你有帮助!


    周雪峰
    2010年4月29日 11:57
    版主
  • 雪峰您好,如果仅仅是两个窗体FROM1和FROM2,FORM1中要动态生成num个textBox,textBox的text属性是一个字符串数据myStr[],点击FORM1中的button,弹出Form2,在Form2中设置好Form1中的num何myStr[],点击确定,FORM1中发生相应变化,这个怎么实现,您能帮我提供个思路吗
    2010年5月5日 3:26
  • 你好!

    在窗体间传递数据的方法比较多:
    1,在子窗体中自定义一个构造函数,参数类型是主窗体,当要显示子窗体的时候,就用这个构造函数来实例化子窗体,然后把this指针传进去,说起来太抽象了,我大概一写大家应该就明白了:
       public class frmMain:Form
       {
            ...
            frmControl controlForm=new frmControl(this);
            controlForm.Show();
        }

        public class frmControl:Form  //子窗体,用来控制主窗体的某些显示!
        {
             private frmMain mainForm;
             public frmControl(frmMain mainForm)
             {
                  this.mainForm=mainForm;
              }
              private void button1_Click(object sender,EventArgs e)

                   {

                               frmMain.textBox1.Text=this.textBox1.Text;  //把子窗体的文本框值传递给主窗体的文本框!

                   }

         }
    2,我个人感觉上面的方法不是很好,虽然实现起来很简单,只是想改变窗体的标题文本,就把整个主窗体的引用都传递给子窗体,这样的方式不是很幽雅,我们用接口来改进上面的方法,这样可以限制暴露给子窗体的功能,降低窗体之间的耦合度:
       public interface IChangeTitle:
       {
            void ChangeTitle(string title);
        }
       public class frmMain:Form,IChangeTitle
       {
            ...
            frmControl controlForm=new frmControl(this);
            controlForm.Show();
            public void ChangeTitle(string title)
            {
                 this.Text=title;
             }       
        }

        public class frmControl:Form  //子窗体,用来控制主窗体的某些显示!
        {
             private IChangeTitle ichangeTitle;
             public frmControl(IChangeTitle ichangeTitle)
             {
                  this.ichangeTitle=ichangeTitle;
              }
              private void button1_Click(object sender,EventArgs e)

                   {

                               ichangeTitle.ChangeTitle(this.textBox1.Text);  //通过接口来调用方法

                   }

         }
    3,为了进一步降低窗体之间的耦合度,我们可以用委托来实现这个需求:
        public partial class ChildForm : Form
        {
            public delegate void TitleChangedHandler(string title);
            public TitleChangedEventHandler TitleChanged;
            public ChildForm()
            {
                InitializeComponent();
            }

           
            private void btn_Ok_Click(object sender, EventArgs e)
            {           
                if (TitleChanged != null)
                    TitleChanged("Test Title"); //委托调用
               
            }
        }
    主窗体给委托变量赋值就可以了:
        public partial class MainForm : Form
        {
            private ChildForm loginForm = new ChildForm();
            public MainForm()
            {
                InitializeComponent();
                loginForm.TitleChanged = new ChildForm.TitleChangedEventHandler(FormTitleChanged);
            }

            protected void FormTitleChanged(string title)
            {
                this.Text = title;
            }

            private void button1_Click(object sender, EventArgs e)
            {
                loginForm.Show();
            }
        }

    4,也可以在子窗体中定义一个自定义的事件,然后自定义一个事件参数,用来传递你想传递的一些信息:
        public partial class ChildForm : Form
        {
            public class TitleChangedEventArgs : EventArgs //事件参数类
            {
                private string title = "";
                public string Title
                {
                    get
                    {
                        return title;
                    }
                    set
                    {
                        title = value;
                    }
                }
            }
            public delegate void TitleChangedEventHandler(object sender, TitleChangedEventArgs e);
            public event TitleChangedEventHandler TitleChanged;
            public ChildForm()
            {
                InitializeComponent();
            }

           
            private void btn_Ok_Click(object sender, EventArgs e)
            {
                TitleChangedEventArgs e1=new TitleChangedEventArgs();
                e1.Title="Login sucessed";
                OnTitleChanged(e1);//触发事件
               
            }

            protected virtual void OnTitleChanged(TitleChangedEventArgs e)   //触发事件的方法
            {
                if (TitleChanged != null)
                    TitleChanged(this, e);
            }
        }

    主窗体订阅这个事件就可以了:
        public partial class MainForm : Form
        {
            private ChildForm loginForm = new ChildForm();
            public MainForm()
            {
                InitializeComponent();
                loginForm.TitleChanged += new ChildForm.TitleChangedEventHandler(FormTitleChanged);
            }

            protected void FormTitleChanged(object sender, ChildForm.TitleChangedEventArgs e)
            {
                this.Text = e.Title;
            }

            private void button1_Click(object sender, EventArgs e)
            {
                loginForm.Show();
            }
        }


    周雪峰
    2010年5月5日 11:46
    版主