Hiding/showing child controls when parent control gains/loses focus
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开发者_JS百科 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?
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();
}
}
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 { /**/ }
}
精彩评论