C#从UserControl更改主窗体的UI
我有一个名为Form1的表单,它的主体是FlowLayoutPanel 这个FlowLayoutPanel列出了一堆用户控件,每当我在UserControl中单击remove按钮时,我都希望FlowLayoutPanel得到更新 它是从名为listTiles的列表进行渲染的:C#从UserControl更改主窗体的UI,c#,winforms,C#,Winforms,我有一个名为Form1的表单,它的主体是FlowLayoutPanel 这个FlowLayoutPanel列出了一堆用户控件,每当我在UserControl中单击remove按钮时,我都希望FlowLayoutPanel得到更新 它是从名为listTiles的列表进行渲染的: public List<BookModel> listTiles = new List<BookModel>(); 有几种方法可以做到这一点,但我会列出一种 事件驱动模型 它的关键是任何特定的
public List<BookModel> listTiles = new List<BookModel>();
有几种方法可以做到这一点,但我会列出一种 事件驱动模型 它的关键是任何特定的子视图都应该有一个事件。让我们假设事件的形式是
event EventHandler<BookModel> RemoveClicked;
最后,在初始化之后,主窗体应该订阅事件。这可以通过设计器完成(事件将在misc.下列出),或直接通过如下代码完成:
public void AddView(YourUserControl someView)
{
InitializeComponent();
someView.RemoveClicked += HandleThatEvent;
}
如果您正在管理流布局,它可能有一些不同的删除方法。。例如,您可能需要向它传递对要删除的控件的引用。因此,如果您不想重新播放,您可能必须聪明地匹配删除的项目。不过,每次列表发生更改时,重新启动整个流控件的速度也一样快。我会先测试一下,如果从列表中重新提交UI,看看它是否有明显的延迟。只需将mainForm的引用传递到用户控件的构造函数中即可。之后,您只需将代码添加到用户控件中RemoveButton的事件处理程序中,即可根据需要更新mainForm上的FlowLayoutPanel
Public Class UserControl
{
private Form main;
UserControl(Form mainForm)
{
initialize();
main = mainForm;
}
ButtonRemoveOnClick(eventArgs e)
{
main.listTiles.Remove(""); //name or index of tile you want removed inside
//parentheses
main.RenderFlowLayoutTiles(); //assuming you have a method to re-render these
//tiles, otherwise, whatever code you need to
//execute to render these tiles would go here
}
}
在UserControl中,您有一个按钮,单击该按钮时应删除UserControl 如果您需要处理引用当前现有UCs的
列表,则在移除UC时,您已通知该列表的所有者(这里显然是一个表单)(我认为,移除意味着处置它)。
通知通常是由对象引发的事件。在这种情况下,用户控件:其内部组件不应直接与外部世界对话
在这种情况下,添加一个public
事件,该事件在单击UC内的按钮时引发:
public partial class MyUserControl : UserControl
{
public delegate void ControlRemoveEventHandler(object sender, EventArgs e);
public event ControlRemoveEventHandler ControlRemoveNotify;
public MyUserControl() => InitializeComponent();
private void btnRemoveControl_Click(object sender, EventArgs e)
=> ControlRemoveNotify?.Invoke(this, e);
}
当用户控件被创建并添加到列表中时,您可以订阅此公共事件(此代码还同时将每个新的用户控件添加到FlowLayoutPanel)
单击UC按钮时,UC将引发ControlRemoveNotify
事件。此事件的处理程序调用RemoveControl((MyUserControl)obj)代码>,从列表中删除UC,然后将其处理。
处理UC时,它也会从FlowLayoutPanel中移除:
private List<MyUserControl> userControls = new List<MyUserControl>();
private void AddUCsToList(int howMany)
{
for (int i = 0; i < howMany; i++)
{
var uc = new MyUserControl();
void RemoveControl(object s, EventArgs e)
{
uc.ControlRemoveNotify -= RemoveControl;
userControls.Remove(uc);
uc.Dispose();
};
uc.ControlRemoveNotify += RemoveControl;
userControls.Add(uc);
flowLayoutPanel1.Controls.Add(uc);
}
}
public partial class MyUserControl : UserControl
{
public MyUserControl() => InitializeComponent();
private void btnRemoveControl_Click(object sender, EventArgs e)
=> this.Dispose();
}
不需要其他任何东西:
private List<MyUserControl> userControls = new List<MyUserControl>();
private void AddUCsToList(int howMany)
{
for (int i = 0; i < howMany; i++)
{
flowLayoutPanel1.Controls.Add(new MyUserControl());
}
}
private List userControls=new List();
私有列表(整数多少)
{
for(int i=0;i<多少;i++)
{
flowLayoutPanel1.Controls.Add(新的MyUserControl());
}
}
请发布表单和用户控件的代码。您不需要。让它提供在单击“删除”时触发的事件。然后主窗体可以注册并相应地处理它。也许告诉OP主窗体也必须注册事件是值得的。拥有一个未注册的处理程序不会起任何作用。传入构造函数不是一个好主意,因为您失去了设计时支持。您总是可以使用找到父窗体,然后可以将其转换为所需的窗体类型或接口,并调用某些方法。但总的来说,这不是一个好主意。例如,使用事件方法是更好的方法
public partial class MyUserControl : UserControl
{
public MyUserControl() => InitializeComponent();
private void btnRemoveControl_Click(object sender, EventArgs e)
=> this.Dispose();
}
private List<MyUserControl> userControls = new List<MyUserControl>();
private void AddUCsToList(int howMany)
{
for (int i = 0; i < howMany; i++)
{
flowLayoutPanel1.Controls.Add(new MyUserControl());
}
}