折叠父级后,按钮单击事件无响应

时间:2013-05-23 07:45:53

标签: wpf button visibility stackpanel

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

<StackPanel x:Name="buttonPanel" Orientation="Horizontal">
    <Button x:Name="ReMindNodeNotes" Content="&#xE104;"
            FontFamily="Segoe UI Symbol" FontSize="14" Foreground="#FF292323" 
            HorizontalAlignment="Left" BorderThickness="1" Padding="0"
            UseLayoutRounding="True" Click="NoteClicked" />
    <Button x:Name="ReMindNodeRemove" Content="&#xE107;"
            FontFamily="Segoe UI Symbol" FontSize="14" Foreground="#FF292323" 
            HorizontalAlignment="Left" BorderThickness="1" Padding="0"
            UseLayoutRounding="True" Click="RemoveClicked" />
</StackPanel>

这是代码(现在只是一些文字):

private void NoteClicked(object sender, RoutedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine("NoteClicked...");
}

private void RemoveClicked(object sender, 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 ...

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

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

当我手动执行此操作时,它可以正常工作!当我试图通过GotFocus和LostFocus事件来实现这一点时,事实并非如此。以下是手动解决方案的代码(可行):

    private void MoreClicked(object sender, RoutedEventArgs e)
    {
        this.buttonPanel.Visibility = 
            this.buttonPanel.Visibility == 
                Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
    }

以下是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;
    }

非常感谢你的帮助! THX再次......

1 个答案:

答案 0 :(得分:0)

感谢您的样品morincer。然而问题有点复杂。让我试着解释一下我在经过一些研究后发现的解决方案。也许其他开发者也可以从中受益。

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

在这种情况下,对我来说最重要的事件是LostFocus事件。当用户控件失去焦点时 - 例如到另一个控件 - 我希望按钮面板消失。由于每次触摸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;
        }
    }

这涵盖了大多数情况。当光标位于TextBox中时,按钮面板将关闭。当用户点击背景时,按钮面板也会关闭。这似乎是一个ScrollViewer(通过调试代码找到)。谁能解释一下这个......?

然而,未涵盖的情况是用户点击另一个用户控件。它当然是在用户点击TextBox(参见代码)时,而不是在用户点击按钮时。我试图比较发送者和FocusManager.GetFocusedElement()。问题是发件人返回usercontrol(这是我正在寻找的)但FocusManager.GetFocusedElement()返回按下的按钮。现在我可以要求它的父级是一个边框然后请求边框父级是一个堆栈面板,依此类推,直到我到达usercontrol。然而,引入了一个代码隐藏文件,其中包含分离设计和逻辑的想法,而这个解决方案将它们再次绑定在一起。如果我要改变XAML,我也必须改变逻辑。对我来说似乎不是正确的解决方案。

我通过在构造函数中为每个usercontrol赋予一个唯一名称来找到一个solotion。然后,我还给出了所有按钮的唯一名称(我不会在我的代码中使用它们)从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进行比较?还是依赖于良好编程的任何其他解决方案?

THX再次