0

我有一个UserControl带有多个StackPanel的。我喜欢根据用户操作隐藏特定面板。启动时可见的AStackPanel为我提供了许多工作按钮。这些按钮在代码隐藏文件中具有单击事件。折叠面板然后使其再次可见后,按钮不再起作用。这是我的一部分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 有焦点,它就可以工作。如果焦点在另一个面板上,则不会。此外,我可能应该提到...用户可以创建用户控件的多个实例。

谢谢


跟进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;
    }

我真的很感谢你的帮助!再次感谢...

4

1 回答 1

0

感谢您的样品morincer。然而,问题要复杂一些。让我尝试解释经过更多研究后找到的解决方案。也许其他开发人员也可以从中受益。

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

在这种情况下,对我来说最重要的事件是 LostFocus 事件。当用户控件失去焦点时 - 例如另一个控件 - 我希望按钮面板消失。由于每次触摸用户控件内的对象时都会触发 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(请参阅代码)时会这样做,但当用户单击按钮时不会。我试图比较 sender 和 FocusManager.GetFocusedElement()。问题是发件人返回用户控件(这是我正在寻找的),但 FocusManager.GetFocusedElement() 返回被按下的按钮。现在我可以要求它是一个边框的父级,然后要求它是一个堆栈面板的边框父级,依此类推,直到我到达用户控件。然而,引入了文件隐藏代码,其想法是拆分设计和逻辑,而该解决方案将再次将它们联系在一起。如果我要更改 XAML,我也必须更改逻辑。对我来说似乎不是正确的解决方案。

我通过在构造函数中给每个用户控件一个唯一的名称找到了一个独奏。然后我也给所有按钮唯一的名称(无论如何我不在我的代码中使用它们)从用户控件的名称开始。这使我可以在运行时比较名称并确定焦点是否已更改为用户控件的另一个实例。这是代码:

    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())进行比较?或者任何其他依赖于良好编程的解决方案?

再次感谢

于 2013-05-30T11:48:57.910 回答