我需要一个带有 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>
如何让它发挥作用?
此行为应该可以解决弹出窗口定位问题。
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>