WPF ComboBox 弹出位置:底部并与右边缘对齐

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5340640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:40:21  来源:igfitidea点击:

WPF ComboBox popup placement : Bottom and aligned to the right edge

wpfcomboboxdrop-down-menuplacement

提问by Thomas Levesque

I'm trying to create a ComboBoxwith a non-standard dropdown alignment. Basically, I want the dropdown to be below the ComboBox, but aligned with the right edge of the ComboBoxinstead of the left edge.

我正在尝试创建一个ComboBox非标准下拉对齐方式。基本上,我希望下拉菜单位于 下方ComboBox,但与 的右边缘ComboBox而不是左边缘对齐。

What a normal ComboBoxlooks like, using PlacementMode="Bottom":

什么是正常的ComboBox,使用PlacementMode="Bottom"

combo box aligned to the left

组合框左对齐

What I want:

我想要的是:

combobox aligned to the right

组合框向右对齐

I tried to play with the Popup.PlacementModeproperty in the template of my ComboBox, but none of the possible values seem to do what I want. Is there a simple way to do it, preferably in pure XAML?

我试图Popup.PlacementMode在 my 的模板中使用该属性ComboBox,但似乎没有一个可能的值符合我的要求。有没有一种简单的方法可以做到这一点,最好是在纯 XAML 中?

回答by vortexwolf

When I opened Expression Blend, I have come up with the solution within a few seconds:

当我打开 Expression Blend 时,我在几秒钟内就想出了解决方案:

<Popup Placement="Left" VerticalOffset="{TemplateBinding ActualHeight}" 
       HorizontalOffset="{TemplateBinding ActualWidth}"

Sometimes this application is more useful than writing xaml by hands, but not so often. enter image description here

有时这个应用程序比手工编写 xaml 更有用,但不是那么频繁。 在此处输入图片说明

回答by serge_gubenko

I would use the "Custom" placementmode for the PopUp and declare a callback to place the popup control into the correct position, like it's shown here: WPF ComboBox DropDown Placement

我会为 PopUp 使用“自定义”放置模式并声明一个回调以将弹出控件放置到正确的位置,如下所示:WPF ComboBox DropDown Placement

See if an example here would work for you:

看看这里的一个例子是否适合你:

public class TestComboBox : ComboBox
{
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var popup = (Popup)Template.FindName("PART_Popup", this);
        popup.Placement = PlacementMode.Custom;
        popup.CustomPopupPlacementCallback += (Size popupSize, Size targetSize, Point offset) => 
            new[] {  new CustomPopupPlacement() { Point = new Point (targetSize.Width-popupSize.Width, targetSize.Height) } };
    }
}

hope this helps, regards

希望这有帮助,问候

回答by Sascha Krumbein

Can someone post the complete xaml code please?

有人可以发布完整的xaml代码吗?

I've tried the following:

我尝试了以下方法:

    <ComboBox Grid.Column="1" Height="24" Width="20" HorizontalAlignment="Right"
              VerticalAlignment="Top"                  
              Name="comboBox2" 
              ItemsSource="{Binding  Source={StaticResource FilterTypes}}" 
              SelectedValue="{Binding Path=SelectedType, Mode=TwoWay}" >

        <ComboBox.Template>
            <ControlTemplate>
                <Popup Placement="Left" VerticalOffset="{TemplateBinding ActualHeight}" 
                        HorizontalOffset="{TemplateBinding ActualWidth}" />
            </ControlTemplate>
        </ComboBox.Template>  
    </ComboBox>  

... after some working and testing I've found a good solution...

...经过一些工作和测试,我找到了一个很好的解决方案......

        <ComboBox.Style>
            <Style TargetType="ComboBox" >                                    
                <Setter Property="Popup.FlowDirection" Value="RightToLeft"/>                  
            </Style>
        </ComboBox.Style>      

回答by Markus Hütter

it's a little hacky, but does work. you just have to change the combobox style.

它有点hacky,但确实有效。您只需要更改组合框样式。

    <Grid Height="40">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <FrameworkElement Name="dummy" Visibility="Collapsed">
                <FrameworkElement.RenderTransform>
                    <TransformGroup x:Name="xformgrp">
                        <TranslateTransform X="{Binding ElementName=PopupContent, Path=ActualWidth}" />
                        <ScaleTransform ScaleX="-1" />
                        <TranslateTransform X="{Binding ElementName=chk, Path=ActualWidth}" />
                    </TransformGroup>
                </FrameworkElement.RenderTransform>
            </FrameworkElement>
            <CheckBox Name="chk" HorizontalAlignment="Center">checkthisout</CheckBox>
            <Popup IsOpen="{Binding IsChecked, ElementName=chk}" PlacementTarget="{Binding ElementName=chk}" Placement="Bottom" HorizontalOffset="{Binding ElementName=dummy, Path=RenderTransform.Value.OffsetX}">
                <TextBlock Name="PopupContent" Foreground="Yellow" Background="Blue">yeah long popupcontent</TextBlock>
            </Popup>
        </Grid>            
    </Grid>

The popups HorizontalOffset just has to get the value of PopupContent.ActualWidth-PlacementTarget.ActualWidth. To get that value I used this trick from Charles Petzold.

弹出窗口 Horizo​​ntalOffset 只需要获取 PopupContent.ActualWidth-PlacementTarget.ActualWidth 的值。为了获得这个价值,我使用了 Charles Petzold 的这个技巧