Выпадающий по нажатию на кнопку Popup


Собственно говоря я совсем не собирался писать о такой элементарной вещи, как выпадающий по нажатию на кнопку Popup, если бы не увидел, как некоторые выполняют эту достаточно примитивную операцию путём написания обработчика клика кнопки и присваивания в нем IsOpen=true (а некоторые особо извращённые ещё и позиционируют попап прям в коде используя PointToScreen/PointFromScreen).
Выпадающий по нажатию на кнопку Popup

Итак создадим WPF-ное приложение, кинем на окно ToggleButton и Popup. Теперь пропишем для Popup-а биндинги:
<ToggleButton HorizontalAlignment="Left" VerticalAlignment="Top" Content="Нажми меня" x:Name="toggleButton"/>
<Popup PlacementTarget="{Binding ElementName=toggleButton, Mode=OneWay}" IsOpen="{Binding Path=IsChecked, ElementName=toggleButton}">
<Border Width="Auto" Height="Auto" CornerRadius="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="#FF000000">
<Grid Width="200" Height="300">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFD3D3D3" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="0.147"/>
</LinearGradientBrush>
</Grid.Background>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Здесь может быть что угодно" TextWrapping="Wrap"/>
</Grid>
</Border>
</Popup>
Первый биндинг отвечает за то к какому элементу привязан Popup - в нашем случае к кнопке. Место относительно кнопки, где он будет показываться определяется свойством Placement, по умолчанию оно стоит в Bottom, что меня вполне устраивает поэтому я не буду его специально задавать. Второй же биндинг отвечает за то, что свойство кнопки IsChecked и свойство Popup-а IsOpen связаны. Т.к. у Popup-а по умолчанию свойство StayOpen установлено в true, следовательно в данном примере открываться/закрываться он будет только по нажатию кнопки. Если же мы хотим, чтоб Popup закрывался при уходе фокуса с него, то выглядеть это должно так:
<ToggleButton HorizontalAlignment="Right" VerticalAlignment="Top" Content="Нажми меня" x:Name="toggleButton2"/>
<Popup PlacementTarget="{Binding ElementName=toggleButton2, Mode=OneWay}" StaysOpen="False" IsOpen="{Binding Path=IsChecked, ElementName=toggleButton2, Mode=TwoWay, UpdateSourceTrigger=Default}">
<Border Width="Auto" Height="Auto" CornerRadius="1,1,1,1" BorderThickness="1,1,1,1" BorderBrush="#FF000000">
<Grid Width="200" Height="300">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFD3D3D3" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="0.147"/>
</LinearGradientBrush>
</Grid.Background>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Здесь тоже может быть что угодно" TextWrapping="Wrap"/>
</Grid>
</Border>
</Popup>
Отличия от предыдущего случая заключаются в том, что у Popup-а StayOpen равняется false и у биндинга mode равен TwoWay, это используется для того, чтоб если Popup скроется при потере фокуса кнопка автоматически отжалась…

Скачать исходники:


PS. Само собой данный метод можно использовать не только с Popup-ами но и с контекстным меню.

КОММЕНТАРИИ


НОВЫЙ КОММЕНТАРИЙ


*жирный*
_курсив_
+подчеркнутый+
! заголовок 1
!! заголовок 2
* список
** список 2
# нумерованый список
## нумерованый список 2
[url:http://www.example.com]
{"без форматирования"}
Полное описание синтаксиса