自定义WPF Popup控件
解决问题
1、WPF Popup 不随着 Window 一起移动的问题
2、WPF Popup 总是显示在最前面
引用命名空间
xmlns:ctrl="clr-namespace:Micro.UI.Controls"
XAML
1 2 | <ctrl:uiPopup x:Name= "canvas" VerticalOffset= "-410" IsOpen= "True" AllowsTransparency= "True" PopupAnimation= "Fade" > </ctrl:uiPopup> |
C#
using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Controls.Primitives; namespace Micro.UI.Controls { public class uiPopup : Popup { /// <summary> /// 是否窗口随动,默认为随动(true) /// </summary> public bool IsPositionUpdate { get { return ( bool )GetValue(IsPositionUpdateProperty); } set { SetValue(IsPositionUpdateProperty, value); } } public static readonly DependencyProperty IsPositionUpdateProperty = DependencyProperty.Register( "IsPositionUpdate" , typeof ( bool ), typeof (uiPopup), new PropertyMetadata( true , new PropertyChangedCallback(IsPositionUpdateChanged))); private static void IsPositionUpdateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { (d as uiPopup).pup_Loaded(d as uiPopup, null ); } /// <summary> /// 加载窗口随动事件 /// </summary> public uiPopup() { this .Loaded += pup_Loaded; } /// <summary> /// 加载窗口随动事件 /// </summary> private void pup_Loaded( object sender, RoutedEventArgs e) { Popup pup = sender as Popup; var win = VisualTreeHelper.GetParent(pup); while (win != null && (win as Window) == null ) { win = VisualTreeHelper.GetParent(win); } if ((win as Window) != null ) { (win as Window).LocationChanged -= PositionChanged; (win as Window).SizeChanged -= PositionChanged; if (IsPositionUpdate) { (win as Window).LocationChanged += PositionChanged; (win as Window).SizeChanged += PositionChanged; } } } /// <summary> /// 刷新位置 /// </summary> private void PositionChanged( object sender, EventArgs e) { try { var method = typeof (Popup).GetMethod( "UpdatePosition" , System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if ( this .IsOpen) { method.Invoke( this , null ); } } catch { return ; } } //是否最前默认为非最前(false) public static DependencyProperty TopmostProperty = Window.TopmostProperty.AddOwner( typeof (Popup), new FrameworkPropertyMetadata( false , OnTopmostChanged)); public bool Topmost { get { return ( bool )GetValue(TopmostProperty); } set { SetValue(TopmostProperty, value); } } private static void OnTopmostChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { (obj as uiPopup).UpdateWindow(); } /// <summary> /// 重写拉开方法,置于非最前 /// </summary> /// <param name="e"></param> protected override void OnOpened(EventArgs e) { UpdateWindow(); } /// <summary> /// 刷新Popup层级 /// </summary> private void UpdateWindow() { var hwnd = ((HwndSource)PresentationSource.FromVisual( this .Child)).Handle; RECT rect; if (NativeMethods.GetWindowRect(hwnd, out rect)) { NativeMethods.SetWindowPos(hwnd, Topmost ? -1 : -2, rect.Left, rect.Top, ( int ) this .Width, ( int ) this .Height, 0); } } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } #region P/Invoke imports & definitions public static class NativeMethods { [DllImport( "user32.dll" )] [ return : MarshalAs(UnmanagedType.Bool)] internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport( "user32" , EntryPoint = "SetWindowPos" )] internal static extern int SetWindowPos(IntPtr hWnd, int hwndInsertAfter, int x, int y, int cx, int cy, int wFlags); } #endregion } } |
"唯有高屋建瓴,方可水到渠成"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2013-08-13 通示jQuery实例方法,未DOM对象添加多个方法