3

私はこの質問の助けを借りてFlowPanelLayoutにUserControlsを設定しました: 各DataTableに対してUserControlを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の空白をクリックした場合にのみ機能し、ユーザーが2つのラベルまたは画像をクリックした場合には機能しないことです。すべての子オブジェクトに対しても機能させるにはどうすればよいですか?

また、選択したUserControlを使用して、選択したユーザーのすべての詳細を表示するフォームを開くなど、他のことを行うにはどうすればよいですか?

4

3 に答える 3

8

私はあなたにいくつかの提案があります。回答の下部に、提案を示すコードを含めました。

提案1:UCでのMouseClickの修正
UserControl(UC)にMouseClickイベントを登録する場合、ラベルなどのUserControlに配置するコントロールではなく、UserControl自体に対して登録します。クリックした場合これらの子コントロールの1つは、基になるUCによってクリックが「表示」されないように制御します。

これを修正するには、すべての子コントロールのMouseClickイベントを登録します。UserControl自体に使用しているのと同じMouseClickイベントハンドラーを登録することもできます。

提案2:UCのBorderStyle
を設定するUCを設定するためのコードをBorderStyleUC自体に移動します。IsSelectedUCが選択されたときにtrueに設定されるパブリックプロパティを作成します。BorderStyleプロパティのセッターで、プロパティの値に応じてUCのプロパティを更新します。

UCのプロパティを公開するIsSelectedと便利です。フォームレベルの変数のようにコントロールの外部でこのステータスを追跡するのではなく、これらのUCのグループにクエリを実行して、どのUCが選択されているかを確認できます。

コメントに応じて編集します。これ
は、FlowLayoutPanelで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がクリックしました。このイベントのハンドラーはIsSelected、セット内のすべてのUC(Form、FlowLayoutPanelなどのコンテナータイプコントロールなど)に対して明示的にfalseに設定され、クリックされたUCのMouseClickハンドラーは、クリックされたUCをに設定しますIsSelected。本当。

UCのグループを管理する別のUserControlタイプを作成することを検討する価値があります。この新しいUserControlは、UCのセットの作成と状態管理のためのコードをカプセル化でき、他のプロジェクトでのUCの使用を容易にするだけでなく、UCをホストするフォームのコードを少しクリーンに保ちます。


私の提案ごとに一連のばらばらのコードスニペットを含めるのではなく、私が話していることを再現できるようにするための最小限のコードであると私が望んでいるものを含めると思いました。

新しいVisualStudioWinformプロジェクトを作成し、クラスに次を使用します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を保持し、いくつかのラベルと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;
        }
    }
}
于 2012-09-27T15:07:10.277 に答える
1

私はこれが古いことを知っていますが、コンテナでUC選択を行う方法に関するいくつかのポインタを探してここに着陸しました。ジェイの答えはうまくいきます。

更新は1つだけです。UsersGrid_Loadメソッドは最上位のコントロールのみを使用し、コンテナーの子は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.
    RegisterMouseEvents(Controls);
}

UserControlに再帰メソッドRegisterMouseEventsを追加します

    private void RegisterMouseEvents(ControlCollection controls)
    {
        foreach (Control control in controls)
        {
            // Subscribe the control to the 
            control.Click += Control_MouseClick;
            if (control.HasChildren) RegisterMouseEvents(control.Controls);
        }
    }
于 2016-07-12T16:28:31.333 に答える
0

GotFocusUserControlでイベントをサブスクライブしてみてください。

警告:

このイベントはバブリングルーティングを使用するため、フォーカスを受け取る要素は、イベントハンドラーが実際にアタッチされている要素ではなく、子要素である可能性があります。イベントデータのソースをチェックして、フォーカスを獲得した実際の要素を特定します。

UIElement.GotFocusイベント

アップデート

この質問は適切かもしれません:.Net(Windowsフォーム)ユーザーコントロールのクリックイベント

于 2012-09-26T18:45:08.483 に答える