我正在创建一个文本编辑控件,其中包含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上覆盖了OnGotFocus
和OnLostFocus
并且适当地隐藏/显示了_formattingToolbar
。这不起作用,因为如果子控件获得焦点,则Silverlight会认为父控件失去焦点。最终结果是试图点击工具栏使其消失。
到目前为止,我找到的唯一解决方案是将事件处理程序连接到每个子控件和父UserControl上的GotFocus
和LostFocus
事件。事件处理程序将调用FocusManager.GetFocusedElement()
,如果发现返回的元素是我的UserControl的子元素,则保持_formattingToolbar
可见,否则将其折叠。我相信这会奏效,但这很难看。
这个想法也有可能是错误的,因为GotFocus / LostFocus是异步触发的,而GetFocusedElement()
是同步确定的。是否有竞争条件导致我的想法失败?
任何人都知道更好的解决方案吗?
答案 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 { /**/ }
}