在WPF中创建水平项目控件/组合框

问题描述 投票:0回答:1

我需要一个带有 popup 的项目控件(因为我需要在数据网格中使用它,因此当它展开时,列宽不受影响),它水平显示项目。理想情况下,它是一个带有水平“下拉菜单”的组合框。如果它不下拉而是弹出组合按钮中心上方(选择该项目或 Esc 键将关闭它),那就更好了。项目是固定大小的正方形 30x30 并且数量很少,因此不需要滚动视图。

我发现这个“代码”根本不起作用(屏幕上没有任何渲染):

<ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120">
    <ComboBox.Items>
        <ComboBoxItem>Item 1</ComboBoxItem>
        <ComboBoxItem>Item 2</ComboBoxItem>
        <ComboBoxItem>Item 3</ComboBoxItem>
    </ComboBox.Items>
    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
        </Style>
    </ComboBox.ItemContainerStyle>
    <ComboBox.Template>
        <ControlTemplate TargetType="{x:Type ComboBox}">
            <Grid>
                <Popup x:Name="PART_Popup" AllowsTransparency="true" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom">
                    <Border x:Name="DropDownBorder" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1">
                        <ScrollViewer x:Name="DropDownScrollViewer">
                            <StackPanel IsItemsHost="true"/>
                        </ScrollViewer>
                    </Border>
                </Popup>
            </Grid>
        </ControlTemplate>
    </ComboBox.Template>
</ComboBox>

如何让它发挥作用?

c# wpf xaml .net-7.0
1个回答
0
投票

此行为应该可以解决弹出窗口定位问题。

using Microsoft.Xaml.Behaviors;
using System;
using System.Runtime.Versioning;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace MCS.UI.WpfUICommon.AttachedProperties
{
[SupportedOSPlatform("windows")]
public class AutoRepositionPopupBehavior : Behavior<Popup>
{
    private const int WM_MOVING = 0x0216;

    // should be moved to a helper class
    private DependencyObject GetTopmostParent(DependencyObject element)
    {
        var current = element;
        var result = element;

        while (current != null)
        {
            result = current;
            current = (current is Visual || current is Visual3D) ?
               VisualTreeHelper.GetParent(current) :
               LogicalTreeHelper.GetParent(current);
        }
        return result;
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        //AssociatedObject.LayoutUpdated += (sender, e) => Update();
        AssociatedObject.Loaded += (sender, e) =>
        {
            if (GetTopmostParent(AssociatedObject.PlacementTarget) is Window root)
            {
                var helper = new WindowInteropHelper(root);
                var hwndSource = HwndSource.FromHwnd(helper.Handle);
                if (hwndSource != null)
                {
                    hwndSource.AddHook(HwndMessageHook);
                }
            }
        };
    }

    private IntPtr HwndMessageHook(IntPtr hWnd,
            int msg, IntPtr wParam,
            IntPtr lParam, ref bool bHandled)
    {
        if (msg == WM_MOVING)
        {
            Update();
        }
        return IntPtr.Zero;
    }

    public void Update()
    {
        // force the popup to update it's position
        var mode = AssociatedObject.Placement;
        AssociatedObject.Placement = PlacementMode.Relative;
        AssociatedObject.Placement = mode;
    }
}
}

以及xaml中的用法:

         xmlns:b="http://schemas.microsoft.com/xaml/behaviors" 
         xmlns:attachedprops="clr-namespace:YourBehaviourNameSpace"

 <Popup .... >
    <b:Interaction.Behaviors>                      
        <attachedprops:AutoRepositionPopupBehavior/>
    </b:Interaction.Behaviors>
</Popup>
© www.soinside.com 2019 - 2024. All rights reserved.