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

时间:2010-12-07 22:16:06

标签: silverlight silverlight-4.0 focus routed-events

我正在创建一个文本编辑控件,其中包含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。这不起作用,因为如果子控件获得焦点,则Si​​lverlight会认为父控件失去焦点。最终结果是试图点击工具栏使其消失。

令人讨厌的解决方案

到目前为止,我找到的唯一解决方案是将事件处理程序连接到每个子控件和父UserControl上的GotFocusLostFocus事件。事件处理程序将调用FocusManager.GetFocusedElement(),如果发现返回的元素是我的UserControl的子元素,则保持_formattingToolbar可见,否则将其折叠。我相信这会奏效,但这很难看。

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

任何人都知道更好的解决方案吗?

2 个答案:

答案 0 :(得分:0)

Nitin Midha,你有正确的想法。这让我恢复了原来的尝试,稍微改变了OnLostFocus就可以了:

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

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

答案 1 :(得分:0)

    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 { /**/ }
    }