Dlaczego IsKeyboardFocusWithin zwraca False, gdy kliknę dziecko elementu?

0

Mam taki Popup, który reaguje na ToggleButton - gdy button ma IsChecked równe True to się pojawia, a jak False to znika.
Dodatkowo, gdy kliknie się gdziekolwiek indziej w programie, to chciałabym, żeby ToggleButton ustawiał się na False, i żeby w efekcie Popup zniknął. Kod, który działa prawie zgodnie z założeniami:

<MultiTrigger>
	<MultiTrigger.Conditions>
		<Condition SourceName="Preview" Property="IsKeyboardFocusWithin" Value="False" />
	</MultiTrigger.Conditions>
	<Setter TargetName="Preview" Property="IsChecked" Value="False" />
</MultiTrigger>
<ToggleButton x:Name="Preview" Width="20" Height="20" 
			  Cursor="Hand"
			  Visibility="Collapsed">
	<Grid>
		<Image Source="{Binding Source={x:Static properties:Resources.PreviewNormal}, Converter={StaticResource BitmapConverter}}"                  
			   Width="20" Height="20" HorizontalAlignment="Left" ToolTip="Pokaż podgląd" />
		
		<Popup x:Name="PreviewPopup"
			   AllowsTransparency="True" 
			   HorizontalAlignment="Right" HorizontalOffset="10" VerticalOffset="0" 
			   PopupAnimation="Fade" Placement="Right" 
			   PlacementTarget="{Binding ElementName=Root}"
			   DataContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
			<Popup.Style>
				<Style TargetType="Popup">
					<Style.Triggers>
						<MultiDataTrigger>
							<MultiDataTrigger.Conditions >
								<Condition Binding="{Binding ShowPreviewText}" Value="True"/>
								<Condition Binding="{Binding ElementName=Preview, Path=IsChecked}" Value="True"/>
							</MultiDataTrigger.Conditions>
							<MultiDataTrigger.Setters>
								<Setter Property="IsOpen" Value="True"/>
							</MultiDataTrigger.Setters>
						</MultiDataTrigger>
					</Style.Triggers>
				</Style>
			</Popup.Style>
			<StackPanel Orientation="Horizontal" VerticalAlignment="Center" x:Name="PopupRoot" >
				<Border Background="{StaticResource DefaultBackgroundBrush}" 
					BorderBrush="{StaticResource DefaultBorderBrush}" 
					BorderThickness="1" Padding="4"
					IsHitTestVisible="True"
					Focusable="False"
					HorizontalAlignment="Stretch">
					<ScrollViewer VerticalScrollBarVisibility="Auto"
								  MaxHeight="200"
								  MaxWidth="530">
						<TextBlock Text="{Binding PreviewText}" />
					</ScrollViewer>
				</Border>
			</StackPanel>
		</Popup>
	</Grid>
</ToggleButton>

Mam jednak problem z jedną sytuacją - gdy użytkownik kliknie wewnątrz Popup'u, to Popup znika... A tego nie chcę. Nie rozumiem, dlaczego tak się dzieje, skoro wg dokumentacji IsKeyboardFocusWithin:

Gets a value indicating whether keyboard focus is anywhere within the element or its visual tree child elements. This is a dependency property.

Rozumiem, że focus ucieka z ToggleButton, ale przecież wciąż znajduje się w dziecku tego elementu, nieprawdaż?
Próbowałam w Border zmienić parametr Focusable na True, jednak efekt działania jest ten sam.

0

Próbując wykminić, co się dzieje z focusem, usunęłam wyżej wspomniany MultiTrigger na Preview, a dodałam o taki:

            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition SourceName="PreviewPopup" Property="IsKeyboardFocusWithin" Value="False" />
                </MultiTrigger.Conditions>
                <Setter TargetName="PreviewTextBlock" Property="Background" Value="Red" />
            </MultiTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition SourceName="PreviewPopup" Property="IsKeyboardFocusWithin" Value="True" />
                </MultiTrigger.Conditions>
                <Setter TargetName="PreviewTextBlock" Property="Background" Value="Green" />
            </MultiTrigger>

Chciałam zrozumieć, kiedy focus jest w Popupie, a kiedy nie. Niestety, wnioski są takie, że z tego nie idzie nic wywnioskować... Struktura Popupu taka sama, tylko TextBlock zyskał Name="PreviewTextBlock".

  1. Kliknięcie w ToggleButton -> pojawia się Popup, TextBlock jest czerwony
  2. Kliknięcie w Scroll -> TextBlock dalej jest czerwony
  3. Kliknięcie w TextBlock -> TextBlock robi się zielony
  4. Kliknięcie w Scroll -> TextBlock dalej jest zielony
  5. Kliknięcie w dokumencie Worda (te elementy są w TaskPane) -> TextBlock dalej jest zielony
  6. Kliknięcie gdzieś indziej w TaskPane -> TextBlock robi się czerwony

Przypomnę, że moim celem jest, by Popup nie znikał, gdy klikamy w niego, a znikał, gdy klikamy poza nim...

1

Dobra, ostatecznie nic mnie nie obchodzi gdzie jest focus. Usunęłam wszystkie MultiTriggery i opierając się na tej odpowiedzi: https://stackoverflow.com/questions/14252180/how-do-i-correctly-bind-a-popup-to-a-togglebutton
Wyciągnęłam Popup z wnętrza ToggleButtona (w przeciwnym wypadku kliknięcie w Popup wyłączało IsChecked na ToggleButton, co wprowadzało dodatkową konfuzję), StayOpen ustawiłam na False i zrobiłam TwoWay Binding łączące IsOpen z IsChecked, oraz na ToggleButton:

IsEnabled="{Binding ElementName=PreviewPopup, Path=IsOpen, Converter={StaticResource InverseBoolConverter}}"

Teraz działa, choć focus dalej jest IMHO zaskakujący, ale już mnie to nie obchodzi ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1