using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace XHandler.Controls { /// /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。 /// /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:XHandler.Controls" /// /// /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:XHandler.Controls;assembly=XHandler.Controls" /// /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用, /// 并重新生成以避免编译错误: /// /// 在解决方案资源管理器中右击目标项目,然后依次单击 /// “添加引用”->“项目”->[浏览查找并选择此项目] /// /// /// 步骤 2) /// 继续操作并在 XAML 文件中使用控件。 /// /// /// /// public class TipsChannel : Grid { private int mark = 0;//sizechange执行次数 public List chs = new List(); public event EventHandler SelectedChangedEvent; static TipsChannel() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TipsChannel), new FrameworkPropertyMetadata(typeof(TipsChannel))); } /// /// 通道数, 目前仅支持8通道 /// public int TotalChannels { get { return (int)GetValue(TotalChannelsProperty); } set { SetValue(TotalChannelsProperty, value); } } public static readonly DependencyProperty TotalChannelsProperty = DependencyProperty.Register("TotalChannels", typeof(int), typeof(TipsChannel), new PropertyMetadata(0, OnTotalChannelChanged)); #region 仅在第一次初始化界面时,设置界面的通道数目 private static void OnTotalChannelChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { //TipsChannel tipsChannel = sender as TipsChannel; //int count = (int)e.NewValue; //tipsChannel.SetTotalChannelCount(count); } #endregion ///// ///// 选中通道集合 ///// //public string Selection //{ // get { return (string)GetValue(SelectionProperty); } // set { SetValue(SelectionProperty, value); } //} //public static readonly DependencyProperty SelectionProperty = // DependencyProperty.Register("Selection", typeof(string), typeof(TipsChannel), new PropertyMetadata("")); /// /// 已被选中通道集合 /// public List SelectedChannels { get { return (List)GetValue(SelectedChannelsProperty); } set { SetValue(SelectedChannelsProperty, value);} } public static readonly DependencyProperty SelectedChannelsProperty = DependencyProperty.Register("SelectedChannels", typeof(List), typeof(TipsChannel), new PropertyMetadata(new List (),OnSelectedChanged)); #region 被选择的通道数变化事件 private static void OnSelectedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { TipsChannel tipsChannel = sender as TipsChannel; tipsChannel.SetSelectedChannels(); } #endregion #region 重新设置被选择的通道 public void SetSelectedChannels() { foreach (var child in Children) { if (child is Ellipse) { Ellipse ellipse = (Ellipse)child; //判断是什么 if (SelectedChannels.Contains((int)ellipse.Tag)) { ellipse.Fill = FindResource("blueBrush") as SolidColorBrush; ellipse.Stroke = FindResource("blueBrush") as SolidColorBrush; } else { ellipse.Fill = Brushes.White; ellipse.Stroke = new SolidColorBrush(Color.FromRgb(0x61, 0x64, 0x67)); } } } } #endregion #region 所有通道是否开启选择编辑 /// /// 可编辑 /// public bool CanEdit { get { return (bool)GetValue(CanEditProperty); } set { SetValue(CanEditProperty, value); } } public static readonly DependencyProperty CanEditProperty = DependencyProperty.Register("CanEdit", typeof(bool), typeof(TipsChannel), new PropertyMetadata(false)); #endregion Rectangle MouseRect; Point startPoint; bool isMouseDown = false; #region 构造函数 public TipsChannel() { InitializeComponent(); } #endregion #region 初始化函数 void InitializeComponent() { Initialized += TipsChannel_Initialized; //SizeChanged += TipsChannel_SizeChanged; PreviewMouseDown += TipsChannel_PreviewMouseDown; PreviewMouseMove += TipsChannel_PreviewMouseMove; PreviewMouseUp += TipsChannel_PreviewMouseUp; MouseLeave += TipsChannel_MouseLeave; } #endregion #region 鼠标离开控件显示区域后,更改鼠标按下状态标志 private void TipsChannel_MouseLeave(object sender, MouseEventArgs e) { isMouseDown = false; } #endregion #region 鼠标抬起控件显示区域后,更改鼠标按下状态标志 private void TipsChannel_PreviewMouseUp(object sender, MouseButtonEventArgs e) { isMouseDown = false; } #endregion #region 鼠标被按下后,在控件内选择通道事件 private void TipsChannel_PreviewMouseMove(object sender, MouseEventArgs e) { if (!CanEdit) return; if (isMouseDown) { Point curPos = e.GetPosition(this); if ((Math.Abs(curPos.X - startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(curPos.Y - startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)) { Rect rect = GetCorrectRect(startPoint, curPos); foreach (var child in Children) { if (child is Ellipse) { Ellipse ellipse = (Ellipse)child; GeneralTransform generalTransform1 = ellipse.TransformToAncestor(this); Point currentPoint = generalTransform1.Transform(new Point(0, 0)); Rect childRect = new Rect(currentPoint.X, currentPoint.Y, ellipse.ActualWidth, ellipse.ActualHeight); if (childRect.IntersectsWith(rect)) { ellipse.Fill = FindResource("blueBrush") as SolidColorBrush; ellipse.Stroke = FindResource("blueBrush") as SolidColorBrush; if (SelectedChannels.Contains((int)ellipse.Tag)) { } else { SelectedChannels.Add((int)ellipse.Tag); } } } } } } } #endregion #region 获取当前鼠标选中的矩形区域 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); } #endregion #region 鼠标按下后事件 private void TipsChannel_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (!CanEdit) return; startPoint = e.GetPosition(this); HitTestResult result = VisualTreeHelper.HitTest(this, startPoint); if (result.VisualHit is Ellipse) { var a = (Ellipse)result.VisualHit; //if (SelectedChannels.Contains((int)a.Tag)) //{ // SelectedChannels.Remove((int)a.Tag); //} //else //{ // SelectedChannels.Add((int)a.Tag); //} isMouseDown = true; ResetSelection(a); } } #endregion #region 重新设置当前选中的区域内的通道 private void ResetSelection(Ellipse e) { foreach (var child in Children) { if (child is Ellipse) { Ellipse ellipse = (Ellipse)child; //判断是什么 if (ellipse.Tag == e.Tag)//当前选中的看看是否已选中,如果选中则变为不选中,如果不选中则变为选中 { if (SelectedChannels.Contains((int)e.Tag)) { ellipse.Fill = Brushes.White; ellipse.Stroke = new SolidColorBrush(Color.FromRgb(0x61, 0x64, 0x67)); SelectedChannels.Remove((int)e.Tag); } else { ellipse.Fill = FindResource("blueBrush") as SolidColorBrush; ellipse.Stroke = FindResource("blueBrush") as SolidColorBrush; SelectedChannels.Add((int)e.Tag); } } //ellipse.Fill = Brushes.White; //ellipse.Stroke = new SolidColorBrush(Color.FromRgb(0x61, 0x64, 0x67)); } } chs = SelectedChannels; if (SelectedChangedEvent != null) { SelectedChangedEvent(this, EventArgs.Empty); } } #endregion //#region 控件显示外观大小变化事件 //private void TipsChannel_SizeChanged(object sender, SizeChangedEventArgs e) //{ // if(mark>=1) // { // return; // } // this.ColumnDefinitions.Clear(); // this.RowDefinitions.Clear(); // this.Children.Clear(); // AddItems(); // mark++; //} //#endregion #region 控件初始化事件, 根据设置的通道总数,构建界面通道显示 private void TipsChannel_Initialized(object sender, EventArgs e) { //if (mark >= 1) //{ // return; //} this.ColumnDefinitions.Clear(); this.RowDefinitions.Clear(); this.Children.Clear(); AddItems(); mark++; } #endregion #region 初始化控件内的通道数目 private void AddItems() { if (TotalChannels > 8) TotalChannels = 8; this.RowDefinitions.Add(new RowDefinition()); this.RowDefinitions.Add(new RowDefinition()); for (int i = 0; i < TotalChannels; i++) { this.ColumnDefinitions.Add(new ColumnDefinition()); } for (int i = 0; i < TotalChannels; i++) { Ellipse ellipse = new Ellipse() { Margin = new Thickness(4, 2, 4, 2), Width = 24, Height = 24, StrokeThickness = 1, Fill = FindResource("blueBrush") as SolidColorBrush, Stroke = FindResource("blueBrush") as SolidColorBrush, Tag = i + 1 }; this.Children.Add(ellipse); if (!SelectedChannels.Contains(i + 1)) { SelectedChannels.Add(i + 1); } Grid.SetRow(ellipse, 0); Grid.SetColumn(ellipse, i); TextBlock tb = new TextBlock() { Text = (i + 1).ToString(), FontSize = 14, HorizontalAlignment = HorizontalAlignment.Center, }; this.Children.Add(tb); Grid.SetRow(tb, 1); Grid.SetColumn(tb, i); } } #endregion #region 重新构建通道显示 public void ResetChannelItems() { SelectedChannels.Clear(); this.ColumnDefinitions.Clear(); this.RowDefinitions.Clear(); this.Children.Clear(); int currentChannelTotal = TotalChannels;//当前通道总数量 this.RowDefinitions.Add(new RowDefinition()); this.RowDefinitions.Add(new RowDefinition()); for (int i = 0; i < currentChannelTotal; i++) { this.ColumnDefinitions.Add(new ColumnDefinition()); } for (int i = 0; i < currentChannelTotal; i++) { #region 构建通道示意圆圈 Ellipse ellipse = new Ellipse() { Margin = new Thickness(4, 2, 4, 2), Width = 24, Height = 24, StrokeThickness = 1, Fill = FindResource("blueBrush") as SolidColorBrush, Stroke = FindResource("blueBrush") as SolidColorBrush, Tag = i + 1 }; this.Children.Add(ellipse); if (!SelectedChannels.Contains(i + 1)) { SelectedChannels.Add(i + 1); } Grid.SetRow(ellipse, 0); Grid.SetColumn(ellipse, i); #endregion #region 构建通道编号文字 TextBlock tb = new TextBlock() { Text = (i + 1).ToString(), FontSize = 14, HorizontalAlignment = HorizontalAlignment.Center, }; this.Children.Add(tb); Grid.SetRow(tb, 1); Grid.SetColumn(tb, i); #endregion } } #endregion #region public void SetTotalChannelCount(int count) { mark = 0; this.ColumnDefinitions.Clear(); this.RowDefinitions.Clear(); this.Children.Clear(); TotalChannels = count; AddItems(); chs = SelectedChannels; } #endregion } }