如何将组合框弹出窗口与左下 wpf 对齐?

Posted

技术标签:

【中文标题】如何将组合框弹出窗口与左下 wpf 对齐?【英文标题】:How to align combobox popup to bottom Left wpf? 【发布时间】:2021-07-17 09:06:20 【问题描述】:

目标: 将组合框弹出窗口与左下角对齐。请查看下面的图片以供参考:

我尝试了什么?我尝试使用 PART_Popup 的 Placement 属性。如果我设置 Placement="Bottom",则弹出窗口将从右下角呈现。看看下面这张图片:

另外,在 VS Designer 中显示正确:

组合框 PART_Popup:

<Popup x:Name="PART_Popup"
       AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="Binding IsDropDownOpen, Mode=TwoWay, RelativeSource=RelativeSource TemplatedParent" Margin="1" PopupAnimation="DynamicResource x:Static SystemParameters.ComboBoxPopupAnimationKey" Placement="Bottom"
       MinWidth="170">
    <themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="TemplateBinding MaxDropDownHeight" MinWidth="Binding ActualWidth, ElementName=templateRoot">
        <Border x:Name="dropDownBorder" BorderBrush="DynamicResource x:Static SystemColors.WindowFrameBrushKey" BorderThickness="1" Background="StaticResource ComboBox.Static.Background"
                CornerRadius="3">
            <ScrollViewer x:Name="DropDownScrollViewer" CanContentScroll="False">
                <Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
                    <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                        <Rectangle x:Name="opaqueRect" Fill="Binding Background, ElementName=dropDownBorder"
Height="Binding ActualHeight, ElementName=dropDownBorder" Width="Binding ActualWidth, ElementName=dropDownBorder"/>
                    </Canvas>
                    <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels"
                                    Margin="16"/>
                </Grid>
            </ScrollViewer>
        </Border>
    </themes:SystemDropShadowChrome>
</Popup>

XAML:

<ComboBox
HorizontalAlignment="Left" 
VerticalAlignment="Center" 
SelectedIndex="0"
Margin="50,0"
Style="StaticResource FlatComboBoxStyle2">
    <ComboBoxItem Content="Recent"/>
    <ComboBoxItem Content="Alphabetical"/>
</ComboBox>

我只在寻找 XAML 代码解决方案。谢谢。

【问题讨论】:

【参考方案1】:

我通过在 App.xaml.cs 中添加转换器来修复它:

    public class PositiveToNegativeConverter:IValueConverter
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        
            return (double) value > 0 ? 0 - (double) value : 0;
        

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        
            throw new NotImplementedException();
        
    

并在我的 ComboBoxTemplate 中定义它:

<PositiveToNegativeConverter x:Key="PositiveToNegativeConverter" />

并在 Popup 的 Horizo​​ntalOffest 中这样称呼它:

HorizontalOffset="Binding ActualWidth, RelativeSource=RelativeSource TemplatedParent, Converter=StaticResource PositiveToNegativeConverter" 

我希望这对寻找解决方案的人有所帮助。

【讨论】:

【参考方案2】:

我遇到了同样的问题,并且在这里关注了几个线程之后(我的所有 XAML 试验都失败了,简而言之,Popup.Placement = [whatever] 在运行时没有改变任何东西)我最终得到了以下“解决方案” .

不漂亮,所以如果你知道我开放的更优雅的方式。

所以我命名了我的 ComboBox 并在 DropDownOpen 上添加了一个事件处理程序(通过 XAML)(这是 imo 的脏端),我将 Popup.Placement 强制设置为 RelativePoint 并将 VerticalOffset 设置为我的 ComboBox.ActualHeight。

这是 XAML 代码:

<ComboBox Name="NIC_CmbBox" HorizontalAlignment="Stretch" DropDownOpened="NIC_CmbBox_DropDownOpened">                    

C#:

private Popup _comboBoxPopup;

private void NIC_CmbBox_DropDownOpened(object sender, EventArgs e)

    ComboPopupPlacement();


public Popup ComboBoxPopup 
    get
    
        if(_comboBoxPopup == null)
        
            //try to get it
            if(NIC_CmbBox != null)
                _comboBoxPopup = (Popup)NIC_CmbBox.Template.FindName("PART_Popup", NIC_CmbBox);
        
        return _comboBoxPopup;
    
    set => _comboBoxPopup = value; 

public void ComboPopupPlacement()
            
    //If placement haven't already be done
    if (ComboBoxPopup != null && _comboBoxPopup.Placement != PlacementMode.RelativePoint)
    
        _comboBoxPopup.Placement = PlacementMode.RelativePoint;
        _comboBoxPopup.VerticalOffset = NIC_CmbBox.ActualHeight;
    

【讨论】:

以上是关于如何将组合框弹出窗口与左下 wpf 对齐?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 MenuItem 弹出窗口与菜单的右下角对齐

有没有办法在点击时从地图框弹出窗口中获取信息?

wpf 窗口弹出问题

WPF 弹出窗口:如何为弹出窗口制作可重复使用的模板?

如何使 WPF 弹出窗口出现在应用程序的右下角?

wpf 如何让弹出窗口总在屏幕范围之内?