957157ae80
## Compilation fixes - Fix XAML namespace reference XplorePlane.Converters → XplorePlane.Helpers (EventLogView, StateDisplayView) - Add missing using for ISampleTypeRepository / JsonSampleTypeRepository in App.xaml.cs - Fix ILoggerService.Warn() calls using Exception as first arg instead of message string - Serialize CncProgram to JSON when passing to MatrixLayout (expects string, not CncProgram object) - Suppress CS8632 nullable annotation warnings project-wide ## BGA wizard fixes - Fix preview not showing on step 3: force RefreshBgaPreview() when entering final step - Add step validation in CanNext() to prevent skipping to preview with invalid inputs - Notify NextCommand.CanExecuteChanged when inputs change - Fix RunProgress runtime binding error: set Mode=OneWay for ProgressBar.Value ## Operator toolbox: prevent duplicate insertion - Add static OperatorTarget property for direct dispatch to active pipeline - PipelineEditorView registers as toolbox target on load (floating window only) - CNC page sets initial target; PipelineEditorWindow resets to CNC pipeline on close - '+' button inserts only to the active pipeline instead of broadcasting to all subscribers ## Pipeline editor status bar messages - Add StatusBarMessageEvent / StatusBarMessagePayload to CommonEvents.cs - PipelineEditorViewModel publishes status on all ops (add/remove/reorder/save/execute) - MainViewModel subscribes and displays on main window bottom status bar - Auto-clear after timeout (3s info, 5s error) ## docs - Merge three architecture docs into consolidated XplorePlane-架构与结构说明.md
94 lines
3.5 KiB
C#
94 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Specialized;
|
|
using System.Windows;
|
|
using System.Windows.Media;
|
|
using System.Windows.Shapes;
|
|
|
|
namespace XP.ImageProcessing.RoiControl
|
|
{
|
|
/// <summary>
|
|
/// 多边形Points附加行为,支持ObservableCollection绑定
|
|
/// </summary>
|
|
public static class PolygonPointsBehavior
|
|
{
|
|
private static readonly Dictionary<Polygon, ObservableCollection<Point>> _attachedCollections
|
|
= new Dictionary<Polygon, ObservableCollection<Point>>();
|
|
|
|
public static ObservableCollection<Point> GetPointsSource(DependencyObject obj)
|
|
{
|
|
return (ObservableCollection<Point>)obj.GetValue(PointsSourceProperty);
|
|
}
|
|
|
|
public static void SetPointsSource(DependencyObject obj, ObservableCollection<Point> value)
|
|
{
|
|
obj.SetValue(PointsSourceProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty PointsSourceProperty =
|
|
DependencyProperty.RegisterAttached(
|
|
"PointsSource",
|
|
typeof(ObservableCollection<Point>),
|
|
typeof(PolygonPointsBehavior),
|
|
new PropertyMetadata(null, OnPointsSourceChanged));
|
|
|
|
private static void OnPointsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (!(d is Polygon polygon))
|
|
return;
|
|
|
|
// 清理旧的订阅
|
|
if (e.OldValue is ObservableCollection<Point> oldCollection)
|
|
{
|
|
oldCollection.CollectionChanged -= GetCollectionChangedHandler(polygon);
|
|
_attachedCollections.Remove(polygon);
|
|
}
|
|
|
|
// 设置新的订阅
|
|
if (e.NewValue is ObservableCollection<Point> newCollection)
|
|
{
|
|
// 初始化Points
|
|
UpdatePolygonPoints(polygon, newCollection);
|
|
|
|
// 监听集合变化
|
|
NotifyCollectionChangedEventHandler handler = (s, args) => UpdatePolygonPoints(polygon, newCollection);
|
|
newCollection.CollectionChanged += handler;
|
|
|
|
// 保存引用以便后续清理
|
|
_attachedCollections[polygon] = newCollection;
|
|
|
|
// 监听Polygon卸载事件以清理资源
|
|
polygon.Unloaded += (s, args) =>
|
|
{
|
|
if (_attachedCollections.TryGetValue(polygon, out var collection))
|
|
{
|
|
collection.CollectionChanged -= handler;
|
|
_attachedCollections.Remove(polygon);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
private static NotifyCollectionChangedEventHandler GetCollectionChangedHandler(Polygon polygon)
|
|
{
|
|
return (s, args) =>
|
|
{
|
|
if (s is ObservableCollection<Point> collection)
|
|
{
|
|
UpdatePolygonPoints(polygon, collection);
|
|
}
|
|
};
|
|
}
|
|
|
|
private static void UpdatePolygonPoints(Polygon polygon, ObservableCollection<Point> points)
|
|
{
|
|
// 使用Dispatcher确保在UI线程更新
|
|
polygon.Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
// 创建新的PointCollection以触发UI更新
|
|
polygon.Points = new PointCollection(points);
|
|
}), System.Windows.Threading.DispatcherPriority.Render);
|
|
}
|
|
}
|
|
} |