1

我正在创建一个文本编辑控件,其中包含一个 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>

初始刺

起初我尝试了明显的,我覆盖了父 UserControlOnGotFocus并适当地OnLostFocus隐藏/显示_formattingToolbar。这不起作用,因为如果子控件获得焦点,Silverlight 会认为父控件失去焦点。最终结果是试图单击工具栏导致它消失。

讨厌的解决方案

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

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

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

4

2 回答 2

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 { /**/ }
    }
于 2014-05-20T22:31:17.273 回答
0

Nitin Midha,你的想法是对的。这让我回到了最初的尝试,并稍微改变OnLostFocus了诀窍:

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

        if (!IsChild(FocusManager.GetFocusedElement()))
        {
            HideToolbar();
        }
    }
于 2010-12-07T22:34:29.970 回答