c# - 从 FlowLayoutPanel 选择 UserControl

标签 c# select user-controls flowlayoutpanel

我已经在这个问题的帮助下在 FlowPanelLayout 中设置了 UserControls: For Each DataTable Add UserControl to FlowLayoutPanel

我现在正在尝试实现一个单击事件,它允许我在已选择的 UserControl 周围放置一个边框。我这样做了:

        private void User_Load(object sender, EventArgs e)
    {
        flowlayoutpanelUsers.HorizontalScroll.Visible = false;

        // Load and Sort Users DataTable
        DataTable datatableUsers = UserMethods.GetUsers().Tables["Users"];
        datatableUsers.DefaultView.Sort = "Name";
        DataView dataviewUsers = datatableUsers.DefaultView;

        // Loop Through Rows and Add UsersGrid to FlowLayoutPael
        foreach (DataRowView datarowviewUsers in dataviewUsers)
        {
            var UsersGrid = new UsersGrid
            {
                Username = datarowviewUsers["Username"].ToString(),
                User = datarowviewUsers["Name"].ToString(),
                Admin = datarowviewUsers["Administrator"].ToString(),
            };
            flowlayoutpanelUsers.Controls.Add(UsersGrid);
            UsersGrid.MouseClick += new MouseEventHandler(user_click);
        }
    }

    private UsersGrid selectedUser;

    void user_click(object sender, EventArgs e)
    {
        if (selectedUser != null)
            selectedUser.BorderStyle = BorderStyle.None;
        selectedUser = (UsersGrid)sender;
        selectedUser.BorderStyle = BorderStyle.FixedSingle;
    }

我的问题是,它仅在我单击 UserControl 中的空白区域时有效,但在用户单击两个标签或图像时无效。我如何让它也适用于所有子对象?

此外,我如何才能使用选定的 UserControl 执行其他操作,例如打开一个显示该选定用户的所有详细信息的表单?

最佳答案

我有一些建议给你。在我的回复底部,我包含了展示我的建议的代码。

建议 1:修复 UC 中的 MouseClick
当您为 UserControl (UC) 注册 MouseClick 事件时,您是在为 UserControl 本身这样做,而不是为您放置在 UserControl 上的任何控件(例如标签等)注册 MouseClick 事件。如果您单击这些子控件之一,则单击会成功不会被底层 UC“看到”。

要解决此问题,请为所有子控件注册 MouseClick 事件;您甚至可以为 UserControl 本身注册相同的 MouseClick 事件处理程序。

建议2:设置UC的BorderStyle
我会将您用于设置 UC 的 BorderStyle 的代码移至 UC 本身。创建在选择 UC 时设置为 true 的公共(public)属性 IsSelected。在属性的 setter 中,根据属性的值更新 UC 的 BorderStyle 属性。

为您的 UC 公开一个 IsSelected 属性可能很方便:您可以查询一组这些 UC 以查看哪些被选中,而不是像通过表单那样尝试在控件之外跟踪此状态级变量。

根据您的评论进行编辑:
下面是一个示例,说明您可以如何查询 FlowLayoutPanel 中的 UC 以查看是否选择了任何 UC,如果找到了您可以如何采取一些行动。在这种情况下,操作是调用 EditUser 方法,该方法将您从所选 UC 中的属性中获取的值作为参数值:

var selectedUC = flowLayoutPanel.Controls.Cast<UserControl1>().FirstOrDefault(uc => uc.IsSelected);
if (selectedUC != null) {
    // Use the properties of the UC found to be selected as parameters is method EditUser.
    EditUser(selectedUC.Name, selectedUC.Username, selectedUC.Administrator);
}

建议 3:管理一组 UC 的选择
如果您想取消选择组中除用户单击(即选择)之外的所有 UC,您需要在您的 UC 中创建一个事件,该事件在单击 UC 时触发。此事件的处理程序显式地将集合中所有 UC 的 IsSelected 设置为 false(例如在容器类型控件中,例如 Form、FlowLayoutPanel 等),UC 中的 MouseClick 处理程序是点击后会将被点击的 UC 的 IsSelected 设置为 true。

值得考虑创建另一种 UserControl 类型来管理一组 UC。这个新的 UserControl 可以封装用于创建和管理您的 UC 集的代码,并有助于在其他项目中使用您的 UC,并使托管您的 UC 的表单代码更加简洁。


我想与其为我的每条建议包含一系列不连贯的代码片段,不如包含我希望的最少代码量,让您能够重现我正在谈论的内容。

创建一个新的 Visual Studio Winform 项目并为 Form1 类使用以下内容:

public partial class Form1 : Form
{
    public Form1() {
        InitializeComponent();

        flowLayoutPanel = new FlowLayoutPanel {
            Dock = DockStyle.Fill,
        };
        this.Controls.Add(flowLayoutPanel);
        // Add several sample UCs.
        for (int i = 0; i < 10; i++) {
            var uc = new UserControl1();
            uc.WasClicked += UsersGrid_WasClicked;
            flowLayoutPanel.Controls.Add(uc);
        }
    }

    FlowLayoutPanel flowLayoutPanel;

    // Event handler for when MouseClick is raised in a UserControl.
    void UsersGrid_WasClicked(object sender, EventArgs e) {
        // Set IsSelected for all UCs in the FlowLayoutPanel to false. 
        foreach (Control c in flowLayoutPanel.Controls) {
            if (c is UserControl1) {
                ((UserControl1)c).IsSelected = false;
            }
        }
    }
}

接下来向项目中添加一个UserControl。保留名称 UserControl1 并添加几个 Labels 和一个 PictureBox。将此代码用于类 UserControl1:

public partial class UserControl1 : UserControl
{
    public UserControl1() {
        InitializeComponent();
        this.Load += UsersGrid_Load;
    }

    // Event fires when the MouseClick event fires for the UC or any of its child controls.
    public event EventHandler<EventArgs> WasClicked;

    private void UsersGrid_Load(object sender, EventArgs e) {
        // Register the MouseClick event with the UC's surface.
        this.MouseClick += Control_MouseClick;
        // Register MouseClick with all child controls.
        foreach (Control control in Controls) {
            control.MouseClick += Control_MouseClick;
        }
    }

    private void Control_MouseClick(object sender, MouseEventArgs e) {
        var wasClicked = WasClicked;
        if (wasClicked != null) {
            WasClicked(this, EventArgs.Empty);
        }
         // Select this UC on click.
         IsSelected = true;
    }

    private bool _isSelected;
    public bool IsSelected {
        get { return _isSelected; }
        set {
            _isSelected = value;
            this.BorderStyle = IsSelected ? BorderStyle.Fixed3D : BorderStyle.None;
        }
    }
}

关于c# - 从 FlowLayoutPanel 选择 UserControl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12608300/

相关文章:

.net - 带有嵌套控件的设计模式

c# - 从其基类调用继承的方法

c# - 方法运行时 Richbox 不更新

c# - WebBrowser 控制焦点

MySQL SELECT INTO <variable> 返回 null 但查询返回一个值

css - Android 下拉(选择)CSS

SQL 计算具有不同值的行

wpf - 将 UserControl 中元素的 ItemSource 绑定(bind)到父 ViewModel 中的项目

c# - 在同一页面上使用两个用户控件?

c# - 如何找到 DLL 入口点?