using System.Windows.Media;
using System.Windows;
using System.Windows.Threading;
using System.Windows.Controls;
namespace SeqEditor.Util
{
public class DispatcherHelper
{
private static readonly DispatcherOperationCallback exitFrameCallback = ExitFrame;
///
/// Processes all UI messages currently in the message queue.
///
public static void WaitForPriority()
{
// Create new nested message pump.
DispatcherFrame nestedFrame = new DispatcherFrame();
// Dispatch a callback to the current message queue, when getting called,
// this callback will end the nested message loop.
// The priority of this callback should be lower than that of event message you want to process.
DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.ApplicationIdle, exitFrameCallback, nestedFrame);
// pump the nested message loop, the nested message loop will immediately
// process the messages left inside the message queue.
Dispatcher.PushFrame(nestedFrame);
// If the "exitFrame" callback is not finished, abort it.
if (exitOperation.Status != DispatcherOperationStatus.Completed)
{
exitOperation.Abort();
}
}
private static Object ExitFrame(Object state)
{
DispatcherFrame frame = state as DispatcherFrame;
// Exit the nested message loop.
frame.Continue = false;
return null;
}
public static T FindControl(object obj)
{
if (obj == null)
{
return default(T);
}
if (obj is T target)
{
return target;
}
return FindControl(VisualTreeHelper.GetParent((DependencyObject)obj));
}
public static bool IsElementVisibleInScrollViewer(ScrollViewer scrollViewer, DependencyObject element)
{
if (scrollViewer == null || element == null)
return false;
// 将 element 转换为 FrameworkElement
var frameworkElement = element as FrameworkElement;
if (frameworkElement == null)
return false;
try
{
// 获取元素相对于 ScrollViewer 的坐标变换
GeneralTransform transform = frameworkElement.TransformToVisual(scrollViewer);
// 计算元素在 ScrollViewer 坐标系中的位置和大小
Rect elementRect = new Rect(
transform.Transform(new Point(0, 0)),
transform.Transform(new Point(frameworkElement.ActualWidth, frameworkElement.ActualHeight))
);
// ScrollViewer 的视区矩形
Rect viewportRect = new Rect(
0,
0,
scrollViewer.ViewportWidth,
scrollViewer.ViewportHeight
);
// 检查是否相交(部分可见也算可见)
//return viewportRect.IntersectsWith(elementRect);
// 如果需要完全可见,使用以下代码:
return viewportRect.Contains(elementRect);
}
catch (ArgumentException)
{
// 如果元素尚未加载或不可见,TransformToVisual 可能抛出异常
return false;
}
}
///
/// 查找第一个指定类型的子控件
///
public static T FindVisualChild(DependencyObject parent) where T : DependencyObject
{
if (parent == null)
return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// 找到指定类型
if (child is T t)
return t;
// 递归查找
var result = FindVisualChild(child);
if (result != null)
return result;
}
return null;
}
}
}