using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using XHandler.Class; using XHandler.Class.DataEx; using XImagingXhandler.XDAL; namespace XHandler.Controls { /// /// WellPlate.xaml 的交互逻辑 /// public partial class WellPlate : UserControl { #region custom event /// /// 选中列事件,参数为选中的列数 /// public static readonly RoutedEvent SelectedRoutedEvent = EventManager.RegisterRoutedEvent("SelectedEvent", RoutingStrategy.Bubble, typeof(CustomEvent.CustomRoutedEventHandler), typeof(WellPlate)); [Description("SelectedEvent")] public event CustomEvent.CustomRoutedEventHandler SelectedEvent { add { this.AddHandler(SelectedRoutedEvent, value); } remove { this.RemoveHandler(SelectedRoutedEvent, value); } } private void RaiseSelectEvent(string str) { CustomRoutedEventArgs arg = new CustomRoutedEventArgs(SelectedRoutedEvent, str); this.RaiseEvent(arg); } #endregion public static readonly DependencyProperty SelectOrientationProperty = DependencyProperty.Register("SelectOrientation", typeof(int), typeof(WellPlate), new FrameworkPropertyMetadata((int)1, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(SelectOrientationChanged), null)); /// /// 选择方向 0:水平方向 1:垂直方向 /// public int SelectOrientation { get { return (int)GetValue(SelectOrientationProperty); } set { SetValue(SelectOrientationProperty, value); } } private static void SelectOrientationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { WellPlate plate = sender as WellPlate; } public static readonly DependencyProperty SelectTypeProperty = DependencyProperty.Register("SelectType", typeof(int), typeof(WellPlate), new FrameworkPropertyMetadata((int)1, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(SelectOrientationChanged), null)); /// /// 选择模式 1:单个孔 8:1列 /// public int SelectType { get { return (int)GetValue(SelectTypeProperty); } set { SetValue(SelectTypeProperty, value); } } /// /// 行数 /// public static readonly DependencyProperty RowsProperty = DependencyProperty.Register("Rows", typeof(int), typeof(WellPlate), new FrameworkPropertyMetadata((int)8)); public int Rows { get { return (int)GetValue(RowsProperty); } set { SetValue(RowsProperty, value); } } /// /// 列数 /// public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(int), typeof(WellPlate), new FrameworkPropertyMetadata((int)12, OnCountChanged)); public static ObservableCollection labwareWellInfoListLocal = null; /// /// 耗材的孔位数据 /// public ObservableCollection labwareWellInfoList { get { return (ObservableCollection)GetValue(LabwareWellInfoProperty); } set { SetValue(LabwareWellInfoProperty, value); } } public static readonly DependencyProperty LabwareWellInfoProperty = DependencyProperty.Register("labwareWellInfoListPlane", typeof(ObservableCollection), typeof(WellPlate), new PropertyMetadata(null)); public static double LabwareRealLengthLocal = 0d; /// /// 耗材的实际长 /// public double LabwareRealLength { get { return (double)GetValue(LabwareRealLengthProperty); } set { SetValue(LabwareRealLengthProperty, value); } } public static readonly DependencyProperty LabwareRealLengthProperty = DependencyProperty.Register("LabwareRealLengthPlane", typeof(double), typeof(WellPlate), new PropertyMetadata(Double.NaN, null)); public static double LabwareRealWidthLocal = 0d; /// /// 耗材的实际宽 /// public double LabwareRealWidth { get { return (double)GetValue(LabwareRealWidthProperty); } set { SetValue(LabwareRealWidthProperty, value); } } public static readonly DependencyProperty LabwareRealWidthProperty = DependencyProperty.Register("LabwareRealWidthPlane", typeof(double), typeof(WellPlate), new PropertyMetadata(Double.NaN, null)); public int Columns { get { return (int)GetValue(ColumnsProperty); } set { SetValue(ColumnsProperty, value); } } public static void OnCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { WellPlate plate = (WellPlate)d; Debug.WriteLine("rows=" + plate.Rows.ToString() + ", columns=" + plate.Columns.ToString()); //plate.SetData(); //plate.labwareWellInfoList = labwareWellInfoListLocal; //plate.LabwareRealLength = LabwareRealLengthLocal; //plate.LabwareRealWidth = LabwareRealWidthLocal; plate.AddWellsCircle(); } private void SetData() { //labwareWellInfoListLocal=labwareWellInfoList; //LabwareRealLengthLocal= LabwareRealLength; //LabwareRealWidthLocal = LabwareRealWidth; } public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register("Selection", typeof(string), typeof(WellPlate), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnSelectionChanged), null)); /// /// 选择内容 /// public string Selection { get { return (string)GetValue(SelectionProperty); } set { SetValue(SelectionProperty, value); } } private static void OnSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { WellPlate plate = sender as WellPlate; string str = (string)e.NewValue; plate.SetSelection(str); } private List list = new List(); private Point startPoint; public WellPlate() { InitializeComponent(); } private void idGrid_PreviewMouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { Point curPos = e.GetPosition(idGrid); if ((Math.Abs(curPos.X - startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(curPos.Y - startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)) { Rect rect = GetCorrectRect(startPoint, curPos); List listCol = new List(); foreach (var child in idGrid.Children) { if (child is Rectangle) { Rectangle rectangle = (Rectangle)child; GeneralTransform generalTransform1 = rectangle.TransformToAncestor(idGrid); Point currentPoint = generalTransform1.Transform(new Point(0, 0)); Rect childRect = new Rect(currentPoint.X, currentPoint.Y, rectangle.ActualWidth, rectangle.ActualHeight); if (SelectType == 1) { if (childRect.IntersectsWith(rect)) { rectangle.Fill = FindResource("blueBrush") as SolidColorBrush; if (!isExistWellName(Selection, rectangle.Name)) { if (Selection == "") { Selection += rectangle.Name; } else { if (isExistWellName(Selection, rectangle.Name)) { } else { Selection += "," + rectangle.Name; } } } } else { rectangle.Fill = Brushes.White; if (isExistWellName(Selection, rectangle.Name)) { Selection = dealWellNames(Selection, rectangle.Name); } } } else if (SelectType == 8) { if (childRect.IntersectsWith(rect)) { int col = Grid.GetColumn(rectangle); listCol.Add(col); for (int i = 0; i < Rows; i++) { int index = col * Rows + i; Rectangle rt = idGrid.Children[index] as Rectangle; rt.Fill = FindResource("blueBrush") as SolidColorBrush; if (!isExistWellName(Selection, rt.Name)) { if (Selection == "") { Selection += rectangle.Name; } else { if (isExistWellName(Selection, rectangle.Name)) { } else { Selection += "," + rectangle.Name; } } } } } else { int col = Grid.GetColumn(rectangle); if (listCol.Contains(col)) continue; rectangle.Fill = Brushes.White; if (isExistWellName(Selection, rectangle.Name)) { Selection = dealWellNames(Selection, rectangle.Name); } } } } } } } } private string ChangePosToString(int row, int col) { string ret = ""; char ch = (char)('A' + row); string strRow = ch.ToString(); ret = strRow + (col + 1).ToString(); return ret; } private void UserControl_Loaded(object sender, RoutedEventArgs e) { this.MouseLeave += WellPlate_MouseLeave; idGrid.MouseLeave += idGrid_MouseLeave; idGrid.DataContextChanged += IdGrid_DataContextChanged; AddWellsCircle(); SetSelection(Selection); } private void IdGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { idGrid.ColumnDefinitions.Clear(); idGrid.RowDefinitions.Clear(); idGrid.Children.Clear(); AddWellsCircle(); } private void idGrid_MouseDown(DependencyObject sender, DependencyPropertyChangedEventArgs e) { } private void WellPlate_MouseLeave(object sender, MouseEventArgs e) { } private void idGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { startPoint = e.GetPosition(idGrid); HitTestResult result = VisualTreeHelper.HitTest(idGrid, startPoint); if (result.VisualHit is Rectangle) { var a = (Rectangle)result.VisualHit; ResetSelection(a); } } private void ResetSelection(Rectangle e) { foreach (var child in idGrid.Children) { if (child is Rectangle) { Rectangle ellipse = (Rectangle)child; //判断是什么 if (ellipse.Tag == e.Tag)//当前选中的看看是否已选中,如果选中则变为不选中,如果不选中则变为选中 { if (isExistWellName(Selection, (string)e.Tag)) { ellipse.Fill = Brushes.White; Selection = dealWellNames(Selection, (string)e.Tag); } else { ellipse.Fill = FindResource("blueBrush") as SolidColorBrush; if (string.IsNullOrEmpty(Selection)) { Selection += ((string)e.Tag); } else { Selection += "," + ((string)e.Tag); } } } } } } private string dealWellNames(string wells, string delWell) { string strResult = string.Empty; if (String.IsNullOrEmpty(wells)) { return strResult; } string[] strWells = wells.Split(','); for (int i = 0; i < strWells.Length; i++) { if (strWells[i] != delWell) { strResult += strWells[i] + ","; } } if (!string.IsNullOrEmpty(strResult)) { strResult = strResult.Substring(0, strResult.Length - 1); } return strResult; } private bool isExistWellName(string wells, string tarWell) { if (String.IsNullOrEmpty(wells)) { return false; } bool Result = false; string[] strWells = wells.Split(','); for (int i = 0; i < strWells.Length; i++) { if (strWells[i] == tarWell) { Result = true; } } return Result; } private void idGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { //string str = ""; //foreach(Rectangle rect in idGrid.Children) //{ // if(list.Contains(rect.Name)) // { // if (string.IsNullOrEmpty(str)) // str = rect.Name; // else // str += "," + rect.Name; // } //} //if (Selection == "") //{ // Selection += str; //} //else //{ // if (isExistWellName(Selection, str)) // { // } // else // { // Selection += "," + str; // } //} } private void idGrid_MouseLeave(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { //string str = ""; //foreach (Rectangle rect in idGrid.Children) //{ // if (list.Contains(rect.Name)) // { // if (string.IsNullOrEmpty(str)) // str = rect.Name; // else // str += "," + rect.Name; // } //} //if (Selection == "") //{ // Selection += str; //} //else //{ // if (isExistWellName(Selection,str)) // { // } // else // { // Selection += "," + str; // } //} } } private void UpdatePlate() { try { if (idGrid.Children.Count == 0) return; int count = Rows * Columns; for (int i = 0; i < count; i++) { Rectangle rect = idGrid.Children[i] as Rectangle; if (list.Contains(rect.Name)) rect.Fill = FindResource("blueBrush") as SolidColorBrush; else rect.Fill = Brushes.White; } } catch (Exception ex) { } } public string GetSelected(int col) { string ret = ""; for (int i = 0; i < Rows; i++) { char ch = (char)('A' + i); if (string.IsNullOrEmpty(ret)) ret = ch.ToString() + col.ToString(); else ret += "," + ch.ToString() + col.ToString(); } return ret; } public void CreateWells() { topGrid.Children.Clear(); topGrid.ColumnDefinitions.Clear(); leftGrid.Children.Clear(); leftGrid.RowDefinitions.Clear(); idGrid.Children.Clear(); idGrid.RowDefinitions.Clear(); idGrid.ColumnDefinitions.Clear(); //Selection = ""; for (int column = 0; column < Columns; column++) { topGrid.ColumnDefinitions.Add(new ColumnDefinition()); TextBlock tb = new TextBlock() { Text = (column + 1).ToString(), Style = FindResource("smallTextStyle1") as Style, }; topGrid.Children.Add(tb); Grid.SetColumn(tb, column); idGrid.ColumnDefinitions.Add(new ColumnDefinition()); } for (int row = 0; row < Rows; row++) { leftGrid.RowDefinitions.Add(new RowDefinition()); char ch = (char)('A' + row); TextBlock tb = new TextBlock() { Text = ch.ToString(), Style = FindResource("smallTextStyle2") as Style, }; leftGrid.Children.Add(tb); Grid.SetRow(tb, row); idGrid.RowDefinitions.Add(new RowDefinition()); } for (int column = 0; column < Columns; column++) { for (int row = 0; row < Rows; row++) { Rectangle rectangle = new Rectangle(); rectangle.Name = ChangePosToString(row, column); if (Columns > 12) rectangle.Margin = new Thickness(2, 2, 2, 2); else rectangle.Margin = new Thickness(4, 4, 4, 4); rectangle.Fill = Brushes.White; rectangle.Stroke = Brushes.Gray; rectangle.Tag = rectangle.Name; idGrid.Children.Add(rectangle); Grid.SetRow(rectangle, row); Grid.SetColumn(rectangle, column); } } } /// /// 增加管架孔圈 /// private void AddWellsCircle() { //根据labwareName 获取该耗材内部孔位数据 if (labwareWellInfoList != null) { //先计算出版面比例 double labwareFaceHeight = idGrid.ActualHeight; double labwareFaceWidth = idGrid.ActualWidth; double realHeight = LabwareRealWidth;//LabwareHeight; double realWidth = LabwareRealLength;//LabwareWidth; double widthScale = (double)labwareFaceWidth / realWidth; double heightScale = (double)labwareFaceHeight / realHeight; if (labwareWellInfoList.Count == 0) { CreateWells(); } else { foreach (LabwareWellInfo l in labwareWellInfoList) { Ellipse ellipse = new Ellipse(); ellipse.Name = l.labware_well_name; double diameterVal = l.well_max_length * widthScale; ellipse.Width = diameterVal; ellipse.Height = diameterVal; //ellipse.HorizontalAlignment = HorizontalAlignment.Center; //ellipse.VerticalAlignment = VerticalAlignment.Center; ellipse.Stroke = Brushes.Gray; ellipse.StrokeThickness = 1; ellipse.Fill = Brushes.White; double labwareEllipsePixelx = l.labware_well_center_x * widthScale; double labwareEllipsePixely = l.labware_well_center_y * heightScale; ellipse.Tag = (labwareEllipsePixelx - diameterVal / (double)2).ToString() + "," + (labwareEllipsePixely - diameterVal / (double)2).ToString(); ellipse.Loaded += Ellipse_Loaded; idGrid.Children.Add(ellipse); //ellipse.Margin = new Thickness(20,20, 0, 0); //Grid.SetColumn(ellipse, i); //Grid.SetRow(ellipse, j); //孔位文字 TextBlock textBlock = new TextBlock(); textBlock.Text = l.labware_well_name; textBlock.Width = diameterVal; textBlock.Height = diameterVal; textBlock.Background = Brushes.Transparent; textBlock.Foreground = Brushes.Black; textBlock.Tag = (labwareEllipsePixelx - diameterVal / (double)2).ToString() + "," + (labwareEllipsePixely - diameterVal / (double)2).ToString(); textBlock.Loaded += textBlock_Loaded; idGrid.Children.Add(textBlock); } } } else { CreateWells(); } } private void Ellipse_Loaded(object sender, RoutedEventArgs e) { Ellipse ellipse = sender as Ellipse; ellipse.HorizontalAlignment = HorizontalAlignment.Left; ellipse.VerticalAlignment = VerticalAlignment.Top; string[] strPixels = Convert.ToString(ellipse.Tag).Split(','); ellipse.Margin = new Thickness(Convert.ToDouble(strPixels[0]), Convert.ToDouble(strPixels[1]), 0, 0); } private void textBlock_Loaded(object sender, RoutedEventArgs e) { TextBlock textBlock = sender as TextBlock; textBlock.HorizontalAlignment = HorizontalAlignment.Left; textBlock.VerticalAlignment = VerticalAlignment.Top; string[] strPixels = Convert.ToString(textBlock.Tag).Split(','); textBlock.Margin = new Thickness(Convert.ToDouble(strPixels[0]), Convert.ToDouble(strPixels[1]), 0, 0); } public void SetSelection(string selection) { list.Clear(); if (selection == null) { return; } if (selection.Contains("=")) { return; } string[] ary = selection.Split(','); foreach (string s in ary) { if (string.IsNullOrEmpty(s)) break; string val = s.Substring(1); int col = int.Parse(val); list.Add(s); } UpdatePlate(); } Rect GetCorrectRect(Point start, Point end) { if (end.X < start.X) { double tmp = start.X; start.X = end.X; end.X = tmp; } if (end.Y < start.Y) { double tmp = start.Y; start.Y = end.Y; end.Y = tmp; } return new Rect(start.X, start.Y, end.X - start.X, end.Y - start.Y); } } }