当父控件获得/失去焦点时隐藏/显示子控件

发布于 2024-10-06 16:31:35 字数 1305 浏览 6 评论 0原文

我正在创建一个文本编辑控件,其中包含 RichTextArea 和用于格式化的工具栏。我希望工具栏仅在控件具有焦点时才可见。然而我发现这在 Silverlight 中很难实现,因为 Silverlight 的焦点 API 非常有限。

控件的结构如下:

<UserControl x:Class="MyRichTextBoxControl">
 <Grid>
  <Grid.RowDefinitions>
   <RowDefinition Height="Auto" />
   <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <StackPanel x:Name="_formattingToolBar" Grid.Row="0" Orientation="Horizontal">
   <Button Content="Bold" ... />
   <!-- other buttons -->
  </StackPanel>
  <RichTextBox x:Name="_richTextBox" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
 </Grid>
</UserControl>

初始刺

首先我尝试了显而易见的方法,我覆盖了父 UserControl 上的 OnGotFocusOnLostFocus 并隐藏/显示了 _formattingToolbar > 适当地。这不起作用,因为如果子控件获得焦点,则 Silverlight 会认为父控件失去焦点。最终结果是尝试单击工具栏导致其消失。

令人讨厌的解决方案

到目前为止,我找到的唯一解决方案是将事件处理程序连接到每个子控件和父 UserControl 上的 GotFocus 和 LostFocus 事件。事件处理程序将调用 FocusManager.GetFocusedElement(),如果发现返回的元素是我的 UserControl 的子元素,则保持 _formattingToolbar 可见,否则将其折叠。我确信这会起作用,但它非常丑陋。

这个想法也可能是错误的,因为 GotFocus/LostFocus 是异步触发的,而 GetFocusedElement() 是同步确定的。是否存在竞争条件导致我的想法失败?

有人知道更好的解决方案吗?

I am creating a text editing control that contains a RichTextArea and a toolbar for formatting. I want the toolbar to only be visible when the control has focus. However I am finding this difficult to pull off in Silverlight, as Silverlight's focus API is very limited.

The control is structured like this:

<UserControl x:Class="MyRichTextBoxControl">
 <Grid>
  <Grid.RowDefinitions>
   <RowDefinition Height="Auto" />
   <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <StackPanel x:Name="_formattingToolBar" Grid.Row="0" Orientation="Horizontal">
   <Button Content="Bold" ... />
   <!-- other buttons -->
  </StackPanel>
  <RichTextBox x:Name="_richTextBox" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
 </Grid>
</UserControl>

Initial Stab

At first I tried the obvious, I overrode OnGotFocus and OnLostFocus on the parent UserControl and hid/showed _formattingToolbar appropriately. This does not work, because if a child control gains focus, then Silverlight considers the parent control lost focus. The net result is trying to click on the toolbar causes it to disappear.

Nasty Solution

So far the only solution I have found is to hook up event handlers to the GotFocus and LostFocus events on every single child control and the parent UserControl. The event handler will call FocusManager.GetFocusedElement() and if the returned element is found to be a child of my UserControl, then keep _formattingToolbar visible, otherwise collapse it. I'm sure this will work, but it's pretty ugly.

It's also possible this idea is faulty because GotFocus/LostFocus are fired asynchronously, while GetFocusedElement() is determined synchronously. Could there be race conditions causing my idea to fail?

Anyone know of a better solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ま昔日黯然 2024-10-13 16:31:35

Nitin Midha,你的想法是对的。这让我回到了最初的尝试,稍微改变一下 OnLostFocus 就可以了:

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);

        if (!IsChild(FocusManager.GetFocusedElement()))
        {
            HideToolbar();
        }
    }

Nitin Midha, you had the right idea. That brought my back to my original attempt and a slight altering of OnLostFocus does the trick:

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);

        if (!IsChild(FocusManager.GetFocusedElement()))
        {
            HideToolbar();
        }
    }
巴黎盛开的樱花 2024-10-13 16:31:35
    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);
        object focusedElement = FocusManager.GetFocusedElement();

        if (focusedElement is UIElement)
        {
            if (!this.LayoutRoot.Children.Contains((UIElement)focusedElement))
            {
                // Do your thing.
            }
        }
        else { /**/ }
    }
    protected override void OnLostFocus(RoutedEventArgs e)
    {
        base.OnLostFocus(e);
        object focusedElement = FocusManager.GetFocusedElement();

        if (focusedElement is UIElement)
        {
            if (!this.LayoutRoot.Children.Contains((UIElement)focusedElement))
            {
                // Do your thing.
            }
        }
        else { /**/ }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文