WPF弹出位置问题

4
我是一个有用的助手,可以为您翻译文本。
我遇到了一个奇怪的WPF弹出窗口位置问题。
我已经定义了这个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>

在大多数计算机上,这是预期的结果: correct 然而,在某个特定电脑型号的多台设备上,结果呈现如下: incorrect 有没有办法强制将放置位置设置为顶部和左侧?

这很奇怪!你检查过他们是否都使用相同版本的.NET框架以及两者的显示分辨率是否相同了吗? - Rocklan
所有电脑都运行着1024x768的显示分辨率和相同版本的.NET Framework。我已经尝试了4、4.5和4.5.1,但结果都一样。 - Tommy Mikalsen
1
你修复过这个问题吗?我发现控制弹出窗口是左侧还是右侧的系统设置会影响到这个问题,但我找不到好的解决方案。 - Daniel
不,我从未找到解决方案。那个系统设置在哪里? - Tommy Mikalsen
我在我的用于开发的 HP Envy 笔记本电脑上遇到了相同的问题,其中顶部或底部放置会将弹出窗口右对齐。我们的其他开发人员没有看到这种行为,但他们使用不同的笔记本电脑品牌。显然是机器/配置特定的问题。在目标、弹出窗口和弹出窗口内容上使用 FlowDirection 属性也没有帮助。真糟糕! - Larry S
https://dev59.com/b2Ml5IYBdhLWcg3wzpnV 是一个几乎相同的问题,但有更好的答案。 - Hugh W
5个回答

7
菜单和弹出菜单的左右对齐似乎由这个特殊的注册表键控制:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows
REG_SZ: MenuDropAlignment
Value: 0 表示右对齐
Value: 1 表示左对齐
某种方式,我的系统将菜单和弹出菜单的对齐从右侧改为了左侧。 我检查了这个注册表键,确实是值为1,所以我将其更改回0,现在我的WPF Popup对齐效果正常。

在我的Windows 10上,只有在注销/登录后才会生效注册表中的更改。顺便说一下,这个设置也可以通过从命令行“%windir%\explorer.exe shell:::{80F3F1D5-FECA-45F3-BC32-752C152E456E}”打开平板电脑设置对话框来更改,并且此对话框会立即应用更改。 (详情请参见:https://www.tenforums.com/tutorials/68038-set-menus-open-aligned-left-right-windows-10-a.html) - AntonK

3

更新:如果您想将其应用于整个窗口,则以下是更好的解决方案:WPF弹出窗口中的使用方法

原始内容:

我知道这是一个旧帖子,但我刚刚遇到了这个问题。使用以下代码:

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

我得到了这个:

enter image description here

我不想依赖用户设置,也想避免使用代码和数学。所以我用一个空心矩形在角落里进行了这个肮脏的黑客攻击。好处是所有内置的逻辑,当在屏幕的不同边缘时移动弹出窗口仍然有效:

<!--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}"
    ...

这导致了以下结果:

输入图像描述

完整的代码(应该将矩形放在xaml的顶部,这样它就可以被级联元素覆盖):

<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>

2
我在我的惠普笔记本上解决了这个问题。原来由于它有触摸屏,它使用左/右“惯用性”来选择下拉菜单和弹出窗口与目标控件的左对齐或右对齐(当使用顶部或底部对齐时)。
要解决此问题,请转到控制面板,在搜索框(右上角)中键入“平板电脑设置”。在该对话框中(在某些 Windows 版本的“常规”选项卡下,在其他 PC 上的“其他”选项卡下),您将看到右手和左手操作的选项。
如果菜单和弹出窗口显示在被触摸点的左侧,则右对齐的弹出窗口更好,这样右手就不会遮挡组件。当然,如果您主要使用鼠标,则它看起来很奇怪并会困扰开发人员!

0

我在我正在开发的应用程序中遇到了弹出窗口的同样问题。我不能指望客户更改他们平板电脑上的设置,因此我使用了这段代码来为每个人修复弹出窗口的位置:

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

对我不起作用。 - r2d2

0

前往“系统设置” - “硬件和声音” - “平板电脑设置” - “用于书写的手” - 选择“右手”(弹出窗口、下拉菜单向左对齐) 或“左手”(弹出窗口、下拉菜单向右对齐)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接