winforms 需要在主窗体中将用户控件作为独立控件运行

velaa5lx  于 2023-04-21  发布在  其他
关注(0)|答案(2)|浏览(122)

我有一个主窗体,它由FlowLayoutPanel组成,这个FlowLayoutPanel包含几个名为EffectGroupUserControl的UserControls类,每个EffectGroupUserControl还包含几个SingleEffectUserControl,如下图所示:

每个EffectGroupUserControl都有自己的变量和函数,在EffectGroupUserControl内部,SingleEffectUserControl也有自己的变量和函数,我面临的问题是,当我在EffectGroupUserControl[0]中做一些事情时,它也会影响EffectGroupUserControl 1,我希望它们单独运行而不会相互干扰。
下面是EffectGroupUserControl的完整代码,主窗体中可能有几个EffectGroupUserControl

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace water_fountain2
{
    public partial class EffectGroupUserControl : UserControl
    {
        int EffectGroupUserControl_tableRow = 0;
       
        

        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;    // Turn on WS_EX_COMPOSITED
                return cp;
            }
        }
        public EffectGroupUserControl()
        {
            this.DoubleBuffered = true;
            InitializeComponent();
            Add_SingleEffectUserControl();
          
            

        }
       

        private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

        #region Button For Adding SingleEffectUserControl to EffectGroupUserControl
        //------------------ Add Button for adding Single Effects -------------
        private void button_add_Click(object sender, EventArgs e)
        {
            tableLayoutPanel1.Visible = false;
            tableLayoutPanel1.SuspendLayout();
            //get a reference to the previous existent 
            RowStyle temp = tableLayoutPanel1.RowStyles[tableLayoutPanel1.RowCount - 1];
            //add a new RowStyle as a copy of the previous one
            tableLayoutPanel1.RowStyles.Add(new RowStyle(temp.SizeType, temp.Height));
            //increase panel rows count by one
            ;
            this.Height += 30;
            tableLayoutPanel1.RowCount++;
            tableLayoutPanel1.SetRowSpan(button_add, tableLayoutPanel1.RowCount);
            tableLayoutPanel1.SetRowSpan(label_timing, tableLayoutPanel1.RowCount);
            Add_SingleEffectUserControl();
            tableLayoutPanel1.ResumeLayout();
            tableLayoutPanel1.Visible = true;
        }

        //------------- Method for Adding Single Effect Called by Add Button ----------------------
        private void Add_SingleEffectUserControl()
        {
            SingleEffectUserControl singleeffectUsercontrol = new SingleEffectUserControl(this)
            {
                Anchor = (AnchorStyles)0xF,
            };
            
            tableLayoutPanel1.Controls.Add(singleeffectUsercontrol, 2, EffectGroupUserControl_tableRow);
            tableLayoutPanel1.SetColumnSpan(singleeffectUsercontrol, 7);
            EffectGroupUserControl_tableRow++;

            singleeffects_list.Add(singleeffectUsercontrol);

        }
        #endregion

        #region Remove SingleEffectUserControl from EffectGroupUserControl


        //--------------------- Remove SingleEffectUserControl from EffectGroupUserControl------------------
        public void Remove_SingleEffectUserControl()
        {
            int SingleEffect_index = 0;   //SingleEffect_index for current row
            bool ctl_deleted = false;     // bool value  for SingleEffectUserControl control deleted

            foreach (var seUc_list in singleeffects_list)    // loop in SingleEffectUserControl list for finding which row's cross button clicked
            {
                SingleEffectUserControl singleeffect_Uc = singleeffects_list[SingleEffect_index]; // get SingleEffectUserControl control from list
                if (singleeffect_Uc.Del_SingleEffectUserControl == true)           // If This SingleEffectUserControl's cross button?
                {
                    RemoveArbitraryRow(tableLayoutPanel1, SingleEffect_index);    // Yes Remove that Row
                    singleeffects_list.RemoveAt(SingleEffect_index);
                    ctl_deleted = true;                                           // control has been deleted
                    singleeffect_Uc.Del_SingleEffectUserControl = false;
                    break;                                                        // get out of loop
                }
                SingleEffect_index++;                                            // increment index if this is not the row that fire cross button
            }


            if (ctl_deleted == true)                           // If Control is deleted from above then process below
            { 
                tableLayoutPanel1.SetRowSpan(button_add, tableLayoutPanel1.RowCount);   // set label & button span
                tableLayoutPanel1.SetRowSpan(label_timing, tableLayoutPanel1.RowCount);
                this.Height -= 30;                                                      // set height after deleted row
                EffectGroupUserControl_tableRow--;                                      
            }
        }

        // ---------- Code for Deleting Specific Row is below --------------------------- 
        public void RemoveArbitraryRow(TableLayoutPanel panel, int rowIndex)
        {
            if (rowIndex >= panel.RowCount)
            {
                return;
            }

            // delete all controls of row that we want to delete
            for (int i = 2; i < panel.ColumnCount; i++)   // start from column 2 for SingleEffectUserControl 
            {
                var control = panel.GetControlFromPosition(i, rowIndex);
                panel.Controls.Remove(control);
            }

            // move up row controls that comes after row we want to remove
            for (int i = rowIndex + 1; i < panel.RowCount; i++)
            {
                for (int j = 2; j < panel.ColumnCount; j++)       // start from column 2 for SingleEffectUserControl 
                {
                    var control = panel.GetControlFromPosition(j, i);
                    if (control != null)
                    {
                        panel.SetRow(control, i - 1);
                    }
                }
            }

            var removeStyle = panel.RowCount - 1;

            if (panel.RowStyles.Count > removeStyle)
                panel.RowStyles.RemoveAt(removeStyle);

            panel.RowCount--;
        }
        #endregion

        // Create List for Holding SingleEffectUserControl
        private List<SingleEffectUserControl> singleeffects_list = new List<SingleEffectUserControl>();


    }
}

下面是SingleEffectUserControl的完整代码,当点击十字按钮时设置标志并执行EffectGroupUserControl的函数(SingleEffectUserControl的父):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;

namespace water_fountain2
{

    public partial class SingleEffectUserControl : UserControl
    {
        public bool Del_SingleEffectUserControl = false;
        public EffectGroupUserControl EffectGroupUserControl { get; }

        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;    // Turn on WS_EX_COMPOSITED
                return cp;
            }
        }

        public SingleEffectUserControl(EffectGroupUserControl effectGroupUserControl)
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            EffectGroupUserControl = effectGroupUserControl;

        }


        private void button_add_Click(object sender, EventArgs e)
        {

        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {

        }


        private void devices_comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (devices_comboBox.SelectedIndex)
            {
                case 0:
                    effects_comboBox.Items.Clear();
                    effects_comboBox.Items.Add("Change Pump Capacity");
                    effects_comboBox.Items.Add("Shooting Repeatly");
                    effects_comboBox.Items.Add("Go High then Low");
                    from_textBox.Enabled = true;
                    to_textBox.Enabled = true;

                    break;

                case 1:
                    effects_comboBox.Items.Clear();
                    effects_comboBox.Items.Add("ON in Groups Repeatly");
                    effects_comboBox.Items.Add("ON from inside to outside");
                    effects_comboBox.Items.Add("ON from Left to Right");
                    effects_comboBox.Items.Add("OFF from outside to inside");
                    from_textBox.Enabled = false;
                    to_textBox.Enabled = false;
                    break;

                case 2:
                    effects_comboBox.Items.Clear();
                    effects_comboBox.Items.Add("Red");
                    effects_comboBox.Items.Add("Green");
                    effects_comboBox.Items.Add("Blue");
                    effects_comboBox.Items.Add("Pink");
                    from_textBox.Enabled = false;
                    to_textBox.Enabled = false;
                    break;

            }
        }
        //-------------- Allow Text Boxes to Only Accept Number-------------
        private void from_textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void to_textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void timeON_textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void timeOFF_textbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void remove_button_Click(object sender, EventArgs e)
        {
            Del_SingleEffectUserControl = true;
            EffectGroupUserControl.Remove_SingleEffectUserControl();

        }

        public string Get_to_textbox
        {
            get
            {
                return to_textBox.Text;
            }
            set
            {
                to_textBox.Text = value;
            }
        }

    }
}

请注意,通过在EffectGroupUserControl中添加this解决了这个问题:

SingleEffectUserControl singleeffectUsercontrol = new SingleEffectUserControl(this)
    {
        Anchor = (AnchorStyles)0xF,
    };

SingleEffectUserControl中的这些行:

public bool Del_SingleEffectUserControl = false;
public EffectGroupUserControl EffectGroupUserControl { get; }

protected override CreateParams CreateParams
{
    get
    {
        var cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;    // Turn on WS_EX_COMPOSITED
        return cp;
    }
}

public SingleEffectUserControl(EffectGroupUserControl effectGroupUserControl)
{
    InitializeComponent();
    this.DoubleBuffered = true;
    EffectGroupUserControl = effectGroupUserControl;

}
    private void remove_button_Click(object sender, EventArgs e)
    {
        Del_SingleEffectUserControl = true;
        EffectGroupUserControl.Remove_SingleEffectUserControl();

    }

我正在将SingleEffectUserControl添加到EffectGroupUserControlTableLayoutPanel,这是Parent属性不起作用的原因吗?

4ktjp1zp

4ktjp1zp1#

正如Idle_Mind所说,在创建EffectGroupUserControl的子控件SingleEffectUserControl时,似乎没有考虑到上下层的关系。
在函数中创建父示例时,可以将对父示例的引用传递给每个示例,而不是使用静态示例。
参考我之前的回答
在EffectGroupUserControl中修改

private void Add_SingleEffectUserControl()
{
    SingleEffectUserControl singleeffectUsercontrol = new SingleEffectUserControl(this) // Pass reference of parent EffectGroupUserControl
    {
        Anchor = (AnchorStyles)0xF,
    };

    // Rest of the code
}

在SingleEffectUserControl中修改

private Control parentControl; 

public SingleEffectUserControl( parentControl) 
{
    InitializeComponent();
   parentControl = this.parent;
}

private void remove_button_Click(object sender, EventArgs e)
{
    Del_SingleEffectUserControl = true;
   parentControl.Remove_SingleEffectUserControl(); 
}
ne5o7dgx

ne5o7dgx2#

我不知道沟通的障碍在哪里。
你说过:
@Idle_Mind remove_button_Click()在SingleEffectUserControl控件中
下面是一个简单的SingleEffectUserControl

以下是SingleEffectUserControl的完整代码:

public partial class SingleEffectUserControl : UserControl
{
    public SingleEffectUserControl()
    {
        InitializeComponent();
    }

    private void remove_button_Click(object sender, EventArgs e)
    {
        EffectGroupUserControl g = this.Parent as EffectGroupUserControl;
        g.Controls.Remove(this);
    }
}

下面是EffectGroupUserControl

沿着是EffectGroupUserControl的完整代码:

public partial class EffectGroupUserControl : UserControl
{
    public EffectGroupUserControl()
    {
        InitializeComponent();
    }
}

下面是我的主窗体,上面有两个EffectGroupUserControl

下面是单击Remove按钮时从相应的EffectGroupUserControl中删除的SingleEffectUserControl

相关问题