Reputation: 56
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:
However, on multiple units of one specific computer model, the result is presented like this:
Is there any way to force Placement to both Top AND Left?
Upvotes: 4
Views: 5414
Reputation: 216
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.
Upvotes: 8
Reputation: 1
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)
Upvotes: 0
Reputation: 14250
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:
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:
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>
Upvotes: 4
Reputation: 29
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 });
Upvotes: 0
Reputation: 457
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!
Upvotes: 2