Heinrich
Heinrich

Reputation: 2214

WPF Detecting final placement of Popup

Is it possible to detect the final placement of a popup window? I have a custom popup that renders below a specified UI element and I would like it to draw a border relative to its position to the specified UI control. By default the behaviour is ok, such that the popup is drawn below the control. However as per the popup behaviour if it encounters a screen edge the pop is drawn at a different location. My question is there away to detect were the popups finally position is and then draw the borders respective to its new location. Or does this require a manual process to work out if the popup was drawn in a different location than its default placement.

EDIT:

Below is a picture from Git Extensions as you see there is no line seperating "dev" from the rest of the drop down. Now I have been able to replicate this behaviour all happily. However popups have this neat feature where if the encounter a screen edge the popup will shift accordingly, no this is were my issue comes in because when the popup is shift or rendered at another point I need to pick up this shift and draw the popups borders appropriately. i.e so that if that selection options is popup is drawn above the dev button the the top of the popup will have a complete line and the bottom will have the appropriate gap. When I get a chance I will draw an example.

enter image description here

Upvotes: 4

Views: 2901

Answers (1)

pushpraj
pushpraj

Reputation: 13669

Seems like you are trying to create border around the popup

here is a sample

<Grid>
    <ToggleButton Content="open popup"
                  x:Name="toggle"
                  HorizontalAlignment="Center"
                  VerticalAlignment="Center" />
    <Popup PlacementTarget="{Binding ElementName=toggle}"
           IsOpen="{Binding IsChecked,ElementName=toggle}"
           AllowsTransparency="True">
        <Border Background="White"
                CornerRadius="4"
                BorderBrush="Black"
                BorderThickness="1"
                Padding="5"
                Margin="0,0,10,10">
            <StackPanel>
                <Button Content="somebutton" />
                <RadioButton Content="a radiobutton" />
                <CheckBox Content="a checkbox" />
            </StackPanel>
            <Border.Effect>
                <DropShadowEffect Opacity=".25" />
            </Border.Effect>
        </Border>
    </Popup>
</Grid>

using this approach you'll be able to draw the border or shadow even if some part of the popup is out of the app boundary

result

popup

you can wrap the border and or shadow in a reusable style for re-usability

EDIT

I tried to match with your requirement, also created a reusable template for the same

<Grid RenderOptions.EdgeMode="Aliased">
    <Grid.Resources>
        <ControlTemplate TargetType="HeaderedContentControl"
                         x:Key="PopupButton">
            <Grid>
                <ToggleButton Content="{TemplateBinding Header}"
                              x:Name="toggle"
                              HorizontalAlignment="Center"
                              VerticalAlignment="Center">
                    <ToggleButton.Template>
                        <ControlTemplate TargetType="ToggleButton">
                            <Border BorderBrush="Gray"
                                    Background="White"
                                    BorderThickness="1"
                                    Padding="4"
                                    x:Name="border">
                                <StackPanel Orientation="Horizontal">
                                    <ContentPresenter />
                                    <TextBlock Text="▼"
                                               Margin="4,0,0,0"
                                               FontSize="8"
                                               VerticalAlignment="Center" />
                                </StackPanel>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked"
                                         Value="True">
                                    <Setter Property="BorderThickness"
                                            TargetName="border"
                                            Value="1,1,1,0" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </ToggleButton.Template>
                </ToggleButton>
                <Popup PlacementTarget="{Binding ElementName=toggle}"
                       IsOpen="{Binding IsChecked,ElementName=toggle}"
                       AllowsTransparency="True">
                    <Grid>
                        <Border Background="White"
                                BorderBrush="Gray"
                                BorderThickness="1"
                                Padding="5"
                                Margin="0,0,5,5">
                            <ContentPresenter />
                            <Border.Effect>
                                <DropShadowEffect Opacity=".25" />
                            </Border.Effect>
                        </Border>
                        <Rectangle Fill="White"
                                   Stroke="Transparent"
                                   StrokeThickness="1"
                                   Width="{Binding ActualWidth,ElementName=toggle}"
                                   Height="3"
                                   Margin=".5,-1,0,0"
                                   HorizontalAlignment="Left"
                                   VerticalAlignment="Top" />
                    </Grid>
                </Popup>
            </Grid>
        </ControlTemplate>
    </Grid.Resources>
    <HeaderedContentControl Header="dev"
                            Template="{StaticResource PopupButton}">
        <StackPanel>
            <Button Content="somebutton" />
            <RadioButton Content="a radiobutton" />
            <CheckBox Content="a checkbox" />
        </StackPanel>
    </HeaderedContentControl>
</Grid>

you may define the template in your resources and template in your app for multiple items

eg

    <HeaderedContentControl Header="header"
                            Template="{StaticResource PopupButton}">
        <!--popup content here-->
    </HeaderedContentControl>

result

result

Upvotes: 4

Related Questions