Wpf 按钮单击事件在折叠父级后没有响应

Wpf 按钮单击事件在折叠父级后没有响应,wpf,button,visibility,stackpanel,Wpf,Button,Visibility,Stackpanel,我有一个UserControl,其中有许多StackPanel。我喜欢根据用户操作隐藏特定面板。启动时可见的StackPanel为我提供了许多工作按钮。这些按钮在代码隐藏文件中具有单击事件。折叠面板并使其再次可见后,按钮不再工作。这是我的UserControl的一部分: 下面是代码(目前只提供一些文本): private void NoteClicked(对象发送者,路由目标) { System.Diagnostics.Debug.WriteLine(“NoteClicked…”); } 私

我有一个
UserControl
,其中有许多
StackPanel
。我喜欢根据用户操作隐藏特定面板。启动时可见的
StackPanel
为我提供了许多工作按钮。这些按钮在代码隐藏文件中具有单击事件。折叠面板并使其再次可见后,按钮不再工作。这是我的
UserControl
的一部分:


下面是代码(目前只提供一些文本):

private void NoteClicked(对象发送者,路由目标)
{
System.Diagnostics.Debug.WriteLine(“NoteClicked…”);
}
私有void removeclick(对象发送方,RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(“RemoveClicked…”);
}
过去两天我一直在寻找解决办法。到目前为止运气不好。谁能帮助

THX彼得


后续行动1

以下是折叠面板的代码:

    private void MoreClicked(object sender, RoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine(this.nodeName);
        this.buttonPanel.Visibility =
            this.buttonPanel.Visibility ==
                Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
    }
如果buttonPanel具有焦点,则该选项有效。如果焦点在另一个面板上,则不会。此外,我可能应该提到的是。。。用户可以创建用户控件的多个实例

THX


后续行动2

我继续研究解决方案当然…;-)我找到了一个解决方案,但这不是我想要的解决方案。让我解释一下

用户可以交互地创建前面提到的用户控件的多个实例。创建新实例时,该实例将获得焦点。现在每个实例都有自己的一组按钮,它们位于stackpanel上。当焦点转到另一个实例时,我希望前一个实例的面板折叠。然后应将焦点设置为新实例(或选定的现有实例)

当我手动执行此操作时,它会工作!然而,当我试图通过GotFocus和LostFocus事件来实现这一点时,却没有。以下是手动解决方案的代码(有效):

以下是LostFocus和GotFocus事件:

    private void NodeGotFocus(object sender, RoutedEventArgs e)
    {
        this.buttonPanel.Visibility = Visibility.Visible;
    }

    private void NodeLostFocus(object sender, RoutedEventArgs e)
    {
        this.buttonPanel.Visibility = Visibility.Collapsed;
    }

我真的很感谢你的帮助!再次感谢您的样品morincer。然而,问题有点复杂。让我试着解释一下我在进一步研究后发现的解决方案。也许其他开发者也能从中受益

我将GotFocus和LostFocus事件添加到我的UserConControl中。如果我单击usercontrol中的某个位置,则每次焦点都会改变。奇怪的是,这些事件只在usercontrol本身上定义,而不是在它的子级上定义。我在usercontrol中有几个按钮和一个文本框,例如,当我单击具有焦点的usercontrol的其中一个按钮时,无论如何都会为usercontrol触发LostFocus和GotFocus事件

在这种情况下,对我来说最重要的事件是LostFocus事件。当usercontrol失去焦点时(例如到另一个控件),我希望按钮面板消失。由于每次触摸usercontrol中的对象时都会触发LostFocus事件,因此我无法区分要隐藏和显示按钮的情况

通过如下更改LostFocus事件,我更接近解决方案:

    private void LostFocus(object sender, RoutedEventArgs e)
    {
        Object fo = FocusManager.GetFocusedElement();
        if (fo.GetType().ToString().Contains("TextBox") ||
            fo.GetType().ToString().Contains("ScrollViewer"))
        {
            this.buttonPanel.Visibility = Visibility.Collapsed;
        }
    }
这涵盖了大多数情况。当光标位于文本框中时,按钮面板关闭。当用户单击背景时,按钮面板也会关闭。这似乎是一个ScrollViewer(通过调试代码找到)。谁能解释一下这个

但是,当一个用户单击另一个usercontrol时,这种情况并未涉及。当然,当用户单击文本框(请参见代码)时会出现这种情况,但当用户单击按钮时不会出现这种情况。我试图比较sender和FocusManager.GetFocusedElement()。问题是发送方返回usercontrol(这就是我要找的),但FocusManager.GetFocusedElement()返回被按下的按钮。现在我可以要求它的父对象是一个边框,然后要求它的父对象是一个堆栈面板,依此类推,直到我到达usercontrol。然而,引入了一个代码隐藏文件,其思想是分离设计和逻辑,而这个解决方案将它们再次绑定在一起。如果我要更改XAML,我还必须更改逻辑。对我来说似乎不是正确的解决方案

通过在构造函数中为每个usercontrol指定一个唯一的名称,我找到了一个解决方案。然后,我也会以usercontrol的名称开始为所有按钮指定唯一的名称(无论如何,我在代码中都不会使用它们)。这样我就可以在运行时比较名称,并确定焦点是否已更改为usercontrol的另一个实例。代码如下:

    private void NodeLostFocus(object sender, RoutedEventArgs e)
    {
        Object fo = FocusManager.GetFocusedElement();
        if (fo.GetType().ToString().Contains("ScrollViewer"))
        {
            this.buttonPanel.Visibility = Visibility.Collapsed;
        }
        else if (fo.GetType().ToString().Contains("TextBox"))
        {
            if (!((TextBox)fo).Name.Contains(this.nodeName))
            {
                this.buttonPanel.Visibility = Visibility.Collapsed;
            }
        }
        else if (fo.GetType().ToString().Contains("Button"))
        {
            if (!((Button)fo).Name.Contains(this.nodeName))
            {
                this.buttonPanel.Visibility = Visibility.Collapsed;
            }
        }
    }
现在这个工作!但是…我不喜欢这个解决方案。我依赖于名字,而不是一个好的架构。有人知道如何将实际发送者与按下按钮的父控件(FocusManager.GetFocusedElement())的usercontrol进行比较吗?或者任何其他依赖于良好编程的解决方案


你说的这种行为很奇怪。你能分享一下你折叠面板的代码吗?我把代码添加到了原始的post-Oleg中。还不知道如何添加其他帖子…;-)我已经用您的代码创建了一个示例应用程序,它可以正常工作。问题似乎在于如何在页面上使用控件,而不是事件处理程序本身。顺便说一句,当您在XAML中定义一个名称时,VS会在代码隐藏中创建一个相应的字段,所以您可以这样做。buttonPanel.visibility感谢morincer的提示!我不知道访问面板和按钮可以直接在代码后面访问。你能把样品寄给我吗?那可能真的很有帮助!当然我在你的个人资料中找不到电子邮件,请访问
    private void NodeLostFocus(object sender, RoutedEventArgs e)
    {
        Object fo = FocusManager.GetFocusedElement();
        if (fo.GetType().ToString().Contains("ScrollViewer"))
        {
            this.buttonPanel.Visibility = Visibility.Collapsed;
        }
        else if (fo.GetType().ToString().Contains("TextBox"))
        {
            if (!((TextBox)fo).Name.Contains(this.nodeName))
            {
                this.buttonPanel.Visibility = Visibility.Collapsed;
            }
        }
        else if (fo.GetType().ToString().Contains("Button"))
        {
            if (!((Button)fo).Name.Contains(this.nodeName))
            {
                this.buttonPanel.Visibility = Visibility.Collapsed;
            }
        }
    }