4

I am experiencing a strange WPF popup placement issue.

I have defined this XAML:

<Window x:Class="PositionBug.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="300" Width="525">
<Grid>
    <TextBlock Name="Textblock1" Height="60" Width="300" Background="LightGray" HorizontalAlignment="Center"
               VerticalAlignment="Bottom">The PlacementTarget</TextBlock>
    <Popup Name="Popup1" PlacementTarget="{Binding ElementName=Textblock1}" Placement="Top" Width="120" Margin="198,0,199,0" IsOpen="True">
        <TextBlock Background="LightBlue" FontSize="18">This is a Popup</TextBlock>
    </Popup>
</Grid>

On most computers this is the result, as expected: correct

However, on multiple units of one specific computer model, the result is presented like this: incorrect

Is there any way to force Placement to both Top AND Left?

  • That is a strange one! Did you check that they are both using the same version of the .NET framework and that both display resolutions are the same? – Rocklan Dec 03 '13 at 23:03
  • All the computers are running 1024x768 display resolution and the same version of .NET Framework. I've tried with 4, 4.5 and 4.5.1 with the same result. – Tommy Mikalsen Dec 04 '13 at 08:04
  • 1
    Did you ever fix this? I have found that system setting that control if the popups are left or right influence this but I can not find good solution to this. – Daniel Feb 24 '14 at 18:17
  • No, I never found a solution for this. Where is that system setting? – Tommy Mikalsen Mar 28 '14 at 11:52
  • I'm experiencing the same behavior on my HP Envy laptop that I use for development, where Top or Bottom placement right-aligns the pop-up. Our other developers do not see this behavior, but they have different laptop makes. Definitely seems to be machine/configuration specific. Using FlowDirection property on target, popup, and popup contents did not help either. Darn! – Larry S Jul 16 '15 at 16:43
  • https://stackoverflow.com/q/18113597/1688738 is a near identical question with better answers. – Hugh W Jun 26 '23 at 14:22

5 Answers5

7

The left and right alignment of menus and popups appears to be controlled by this special registry key:

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows

REG_SZ: MenuDropAlignment

Value: 0 means to the right

Value: 1 means to the left

Somehow my system switched the menu and popup alignment from right to left. I checked this registry key and sure enough the value was 1 so I changed it back to 0 and now my WPF Popup alignments are working as expected.

tia.misu
  • 166
  • 1
  • 6
  • on my Windows 10 the change in the registry value becomes effective only after logoff/logon. BTW the setting can also be changed in Windows UI by opening the Tablet PC Settings dialog from command line `%windir%\explorer.exe shell:::{80F3F1D5-FECA-45F3-BC32-752C152E456E}`, and this dialog applies the change immediately (see [more info](https://www.tenforums.com/tutorials/68038-set-menus-open-aligned-left-right-windows-10-a.html) ) – AntonK Nov 28 '22 at 13:26
3

UPDATE: Here is a better solution if you want to make it apply to the entire Window: WPF Handedness with Popups

ORIGINAL:

I realize this is an old thread but I just ran across this. With this:

<Popup 
    Name="Popup"
    Placement="Bottom" 
    PlacementTarget="{Binding ElementName=ToggleButton}"
    ...

I get this:

enter image description here

I didnt want to rely on the user settings and I wanted to avoid code behind and math. So I just did this DIRTY hack but using a hollow rectangle in the corner. Good thing is all of the built-in logic for shifting the popup when at different edges of the screen all still work:

<!--POPUP PLACEMENT HACK-->
<Rectangle 
  x:Name="PART_PopPlacer" 
  Fill="Red"
  Width="0" 
  Height="0"
  HorizontalAlignment="Left"
  VerticalAlignment="Bottom"
  Focusable="False"
  Visibility="Hidden"
  IsHitTestVisible="False"
/>

<Popup 
    Name="Popup"
    Placement="Left" 
    PlacementTarget="{Binding ElementName=PART_PopPlacer}"
    ...

Which gave this:

enter image description here

The full code (should probably put the rectangle at the top of the xaml so it can be covered by the cascading elements):

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
    <!-- COMBO BOX STYLE AND TEMPLATE -->
    <Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
        <Setter Property="MinWidth" Value="120"/>
        <Setter Property="MinHeight" Value="20"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid>

                        <ToggleButton 
                            Background="White"
                            Focusable="false"
                            IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
                            ClickMode="Press"
                          />

                        <ContentPresenter
                            Name="ContentSite"
                            IsHitTestVisible="False" 
                            Content="{TemplateBinding SelectionBoxItem}"
                            Margin="2"
                          />

                        <!--POPUP PLACEMENT HACK-->
                        <Rectangle 
                          x:Name="PART_PopPlacer" 
                          Fill="Red"
                          Width="0" 
                          Height="0"
                          HorizontalAlignment="Left"
                          VerticalAlignment="Bottom"
                          Focusable="False"
                          Visibility="Hidden"
                          IsHitTestVisible="False"
                      />

                        <Popup 
                            Name="Popup"
                            Placement="Left" 
                            PlacementTarget="{Binding ElementName=PART_PopPlacer}"
                            VerticalOffset="6"
                            IsOpen="{TemplateBinding IsDropDownOpen}"
                            AllowsTransparency="True" 
                            Focusable="False"
                            PopupAnimation="Slide">
                            <Grid 
                              Name="DropDown"
                              SnapsToDevicePixels="True">
                                <Border 
                                    Name="DropDownBorder"
                                    Background="LightYellow"
                                    BorderThickness="1"
                                    BorderBrush="Black"/>
                                <ScrollViewer Margin="2" SnapsToDevicePixels="True">
                                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                                </ScrollViewer>
                            </Grid>
                        </Popup>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Page.Resources>

<StackPanel>
    <ComboBox Height="20" Width="50" SelectedIndex="0" Margin="20">
        <ComboBoxItem Content="Very Very Very Very Long Text" />
        <ComboBoxItem Content="Text" />
        <ComboBoxItem Content="Text" />
        <ComboBoxItem Content="Text" />
        <ComboBoxItem Content="Text" />
    </ComboBox>
</StackPanel>

</Page>
Ernie S
  • 13,902
  • 4
  • 52
  • 79
2

I was able to fix this on my HP laptop. Turns out since it has a touch screen, it uses a left/right "handedness" to choose whether drop-down menus and popups are left- or right-aligned with the target control (when using Top or Bottom alignment).

To fix, go to Control Panel, search (upper right corner) and type Tablet PC Settings. On that dialog (under General tab on some versions of Windows, and the Other tab on other PCs) you'll see options for right- and left-handed operation.

The right-justified popups are "better" if the menus and popups show to the left of the point being touched, so the right hand doesn't obscure the component. Of course if you primarily use a mouse, then it just looks weird and confuses us developers!

Larry S
  • 439
  • 5
  • 11
0

I had the same issue with popups in an application I'm working on. I can't expect customers to change the settings on their Tablet PCs, so I used this code to fix the popup positioning for everyone:

var simplePlacement = new CustomPopupPlacement(new Point(0, 0), PopupPrimaryAxis.None);
popup.Placement = PlacementMode.Custom;
popup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback((popupSize, targetSize, offset) => new [] { simplePlacement });
0

Go to "system settings" - "hardware & sound" - "tablet pc-settings" - "to be used writing hand" - select "right-handed" (PopUps, DropDowns align left) or "left-handed" (PopUps, DropDowns align right)