diff --git a/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs b/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs
index b98881a5..334da5a8 100644
--- a/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs
+++ b/Ink Canvas/MainWindow_cs/MW_ElementsControls.cs
@@ -38,6 +38,8 @@ namespace Ink_Canvas
/// 页码侧栏当前订阅 的 PDF 视图。
private PdfEmbeddedView _pdfPageSidebarEventSource;
+ private bool _pdfSidebarPositionRefreshPending;
+
#region Image
///
/// 处理图片插入按钮点击事件
@@ -1581,6 +1583,7 @@ namespace Ink_Canvas
DetachPdfPageSidebarEvents();
_pdfPageSidebarEventSource = pdf;
_pdfPageSidebarEventSource.PageNavigationStateChanged += SelectedPdf_PageNavigationStateChanged;
+ _pdfPageSidebarEventSource.LayoutUpdated += OnPdfSidebarTargetLayoutUpdated;
}
private void DetachPdfPageSidebarEvents()
@@ -1588,10 +1591,55 @@ namespace Ink_Canvas
if (_pdfPageSidebarEventSource != null)
{
_pdfPageSidebarEventSource.PageNavigationStateChanged -= SelectedPdf_PageNavigationStateChanged;
+ _pdfPageSidebarEventSource.LayoutUpdated -= OnPdfSidebarTargetLayoutUpdated;
_pdfPageSidebarEventSource = null;
}
}
+ private void OnPdfSidebarTargetLayoutUpdated(object sender, EventArgs e)
+ {
+ if (BorderPdfPageSidebar?.Visibility != Visibility.Visible || inkCanvas == null) return;
+ if (!(sender is PdfEmbeddedView p) || !ReferenceEquals(_pdfPageSidebarEventSource, p)) return;
+ if (!inkCanvas.Children.Contains(p))
+ SyncPdfPageSidebarWithCanvas();
+ else
+ RequestPdfSidebarPositionRefresh();
+ }
+
+ /// 在下一帧合并更新侧栏位置(初始布局、翻页改尺寸后 ActualWidth 仍为 0 时尤其需要)。
+ private void RequestPdfSidebarPositionRefresh()
+ {
+ if (_pdfSidebarPositionRefreshPending) return;
+ _pdfSidebarPositionRefreshPending = true;
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ _pdfSidebarPositionRefreshPending = false;
+ try
+ {
+ var t = GetPdfSidebarTargetElement();
+ if (t == null || BorderPdfPageSidebar?.Visibility != Visibility.Visible)
+ {
+ SyncPdfPageSidebarWithCanvas();
+ return;
+ }
+
+ if (!inkCanvas.Children.Contains(t))
+ {
+ SyncPdfPageSidebarWithCanvas();
+ return;
+ }
+
+ t.UpdateLayout();
+ inkCanvas.UpdateLayout();
+ UpdatePdfPageSidebarPosition(t);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"PDF 侧栏延迟定位失败: {ex.Message}", LogHelper.LogType.Warning);
+ }
+ }), DispatcherPriority.Render);
+ }
+
///
/// 画布上存在 PDF 时始终显示右侧页码栏并跟随目标 PDF;无任何 PDF 时隐藏。
///
@@ -1620,22 +1668,48 @@ namespace Ink_Canvas
AttachPdfPageSidebarEvents(pdf);
BorderPdfPageSidebar.Visibility = Visibility.Visible;
UpdatePdfSidebarFromPdf(pdf);
+ pdf.UpdateLayout();
+ inkCanvas.UpdateLayout();
UpdatePdfPageSidebarPosition(pdf);
+ RequestPdfSidebarPositionRefresh();
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ var t = GetPdfSidebarTargetElement();
+ if (t != null && BorderPdfPageSidebar?.Visibility == Visibility.Visible && inkCanvas.Children.Contains(t))
+ UpdatePdfPageSidebarPosition(t);
+ }), DispatcherPriority.ContextIdle);
}
///
- /// 将 PDF 专用页码栏贴在当前所选 PDF 的右侧(画布坐标,与底部选中栏一致)。
+ /// 将 PDF 专用页码栏贴在当前 PDF 右侧。侧栏与 InkCanvas 不在同一视觉子树,需把墨迹坐标变换到侧栏父容器坐标系。
///
private void UpdatePdfPageSidebarPosition(FrameworkElement element)
{
try
{
- if (BorderPdfPageSidebar == null || inkCanvas == null || !(element is PdfEmbeddedView))
+ if (BorderPdfPageSidebar == null || inkCanvas == null || !(element is PdfEmbeddedView pdfEl))
return;
- Rect b = GetElementActualBounds(element);
+ if (!inkCanvas.Children.Contains(pdfEl))
+ {
+ SyncPdfPageSidebarWithCanvas();
+ return;
+ }
- BorderPdfPageSidebar.Measure(new Size(BorderPdfPageSidebar.Width, double.PositiveInfinity));
+ pdfEl.UpdateLayout();
+ Rect b = GetElementActualBounds(pdfEl);
+ if (b.Width <= 0 || b.Height <= 0 || double.IsNaN(b.Width) || double.IsNaN(b.Height))
+ {
+ Dispatcher.BeginInvoke(new Action(() =>
+ {
+ var t = GetPdfSidebarTargetElement();
+ if (t is PdfEmbeddedView pe && inkCanvas.Children.Contains(pe) && BorderPdfPageSidebar?.Visibility == Visibility.Visible)
+ UpdatePdfPageSidebarPosition(pe);
+ }), DispatcherPriority.Loaded);
+ return;
+ }
+
+ BorderPdfPageSidebar.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
double sidebarW = BorderPdfPageSidebar.DesiredSize.Width;
double sidebarH = BorderPdfPageSidebar.DesiredSize.Height;
if (sidebarW <= 0)
@@ -1645,17 +1719,64 @@ namespace Ink_Canvas
if (sidebarH <= 0)
sidebarH = 220;
- double left = b.Right + PdfPageSidebarGap;
- double top = b.Top + (b.Height * 0.5) - (sidebarH * 0.5);
+ Visual sidebarHost = VisualTreeHelper.GetParent(BorderPdfPageSidebar) as Visual;
+ double left;
+ double top;
+ double maxLeft;
+ double maxTop;
- double maxLeft = Math.Max(0, inkCanvas.ActualWidth - sidebarW);
- double maxTop = Math.Max(0, inkCanvas.ActualHeight - sidebarH);
-
- if (left > maxLeft)
+ if (sidebarHost != null)
{
- double leftAlt = b.Left - PdfPageSidebarGap - sidebarW;
- if (leftAlt >= 0)
- left = leftAlt;
+ try
+ {
+ GeneralTransform inkToHost = inkCanvas.TransformToVisual(sidebarHost);
+ Point tl = inkToHost.Transform(new Point(b.Left, b.Top));
+ Point br = inkToHost.Transform(new Point(b.Right, b.Bottom));
+ double rightX = Math.Max(tl.X, br.X);
+ double midY = (tl.Y + br.Y) * 0.5;
+ left = rightX + PdfPageSidebarGap;
+ top = midY - sidebarH * 0.5;
+
+ var feHost = sidebarHost as FrameworkElement;
+ double hostW = feHost != null && feHost.ActualWidth > 0 ? feHost.ActualWidth : inkCanvas.ActualWidth;
+ double hostH = feHost != null && feHost.ActualHeight > 0 ? feHost.ActualHeight : inkCanvas.ActualHeight;
+ maxLeft = Math.Max(0, hostW - sidebarW);
+ maxTop = Math.Max(0, hostH - sidebarH);
+
+ if (left > maxLeft)
+ {
+ double leftEdge = Math.Min(tl.X, br.X);
+ double leftAlt = leftEdge - PdfPageSidebarGap - sidebarW;
+ if (leftAlt >= 0)
+ left = leftAlt;
+ }
+ }
+ catch
+ {
+ left = b.Right + PdfPageSidebarGap;
+ top = b.Top + (b.Height * 0.5) - (sidebarH * 0.5);
+ maxLeft = Math.Max(0, inkCanvas.ActualWidth - sidebarW);
+ maxTop = Math.Max(0, inkCanvas.ActualHeight - sidebarH);
+ if (left > maxLeft)
+ {
+ double leftAlt = b.Left - PdfPageSidebarGap - sidebarW;
+ if (leftAlt >= 0)
+ left = leftAlt;
+ }
+ }
+ }
+ else
+ {
+ left = b.Right + PdfPageSidebarGap;
+ top = b.Top + (b.Height * 0.5) - (sidebarH * 0.5);
+ maxLeft = Math.Max(0, inkCanvas.ActualWidth - sidebarW);
+ maxTop = Math.Max(0, inkCanvas.ActualHeight - sidebarH);
+ if (left > maxLeft)
+ {
+ double leftAlt = b.Left - PdfPageSidebarGap - sidebarW;
+ if (leftAlt >= 0)
+ left = leftAlt;
+ }
}
left = Math.Max(0, Math.Min(left, maxLeft));
@@ -2025,8 +2146,15 @@ namespace Ink_Canvas
{
if (sender is PdfEmbeddedView pdf)
{
+ if (!inkCanvas.Children.Contains(pdf))
+ {
+ SyncPdfPageSidebarWithCanvas();
+ return;
+ }
+
UpdatePdfSidebarFromPdf(pdf);
UpdatePdfPageSidebarPosition(pdf);
+ RequestPdfSidebarPositionRefresh();
}
if (currentSelectedElement != null && IsBitmapLikeCanvasElement(currentSelectedElement))
{
@@ -2034,7 +2162,7 @@ namespace Ink_Canvas
if (ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
UpdateImageResizeHandlesPosition(GetElementActualBounds(currentSelectedElement));
}
- }), DispatcherPriority.Background);
+ }), DispatcherPriority.Loaded);
}
private async void BorderPdfSidebarPagePrev_MouseUp(object sender, MouseButtonEventArgs e)
@@ -2044,6 +2172,7 @@ namespace Ink_Canvas
var pdf = GetPdfSidebarTargetElement();
if (pdf != null && pdf.CanGoPrevious)
await pdf.GoToPreviousPageAsync();
+ SyncPdfPageSidebarWithCanvas();
}
catch (Exception ex)
{
@@ -2058,6 +2187,7 @@ namespace Ink_Canvas
var pdf = GetPdfSidebarTargetElement();
if (pdf != null && pdf.CanGoNext)
await pdf.GoToNextPageAsync();
+ SyncPdfPageSidebarWithCanvas();
}
catch (Exception ex)
{
@@ -2091,6 +2221,8 @@ namespace Ink_Canvas
// 恢复到删除前的编辑模式
inkCanvas.EditingMode = previousEditingMode;
+ SyncPdfPageSidebarWithCanvas();
+
LogHelper.WriteLogToFile($"图片删除完成,已恢复到编辑模式: {previousEditingMode}");
}
}