From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点

---
 HMI.UI/Controls/MultiCombox.xaml.cs |  209 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 209 insertions(+), 0 deletions(-)

diff --git a/HMI.UI/Controls/MultiCombox.xaml.cs b/HMI.UI/Controls/MultiCombox.xaml.cs
new file mode 100644
index 0000000..e688cd5
--- /dev/null
+++ b/HMI.UI/Controls/MultiCombox.xaml.cs
@@ -0,0 +1,209 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace HMI.UI
+{
+    public class MultiComboBoxItem : ComboBoxItem, INotifyPropertyChanged
+    {
+        #region ...
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        protected void RaisePropertyChanged(string propertyName)
+        {
+            if (PropertyChanged != null)
+            {
+                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+            }
+        }
+        #endregion
+
+        private MultiComboBox parent;
+        public MultiComboBoxItem(MultiComboBox parent)
+        {
+            this.parent = parent;
+            this.DataContextChanged += MultiComboBoxItem_DataContextChanged;
+        }
+
+        protected override void OnMouseMove(MouseEventArgs e)
+        {
+            this.PreviewMouseUp += MultiComboBoxItem_PreviewMouseUp;
+            base.OnMouseMove(e);
+        }
+
+        protected override void OnMouseLeave(MouseEventArgs e)
+        {
+            this.PreviewMouseUp -= MultiComboBoxItem_PreviewMouseUp;
+            base.OnMouseLeave(e);
+        }
+
+        protected override void OnLostFocus(RoutedEventArgs e)
+        {
+            this.PreviewMouseUp -= MultiComboBoxItem_PreviewMouseUp;
+            base.OnLostFocus(e);
+        }
+
+        private void MultiComboBoxItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+        {
+            if (e.OriginalSource is CheckBox)
+            {
+                // 浠嶤heckBox鐐瑰嚮浼犺繃鏉ョ殑浜嬩欢瑕佹媺鍥炵劍鐐癸紝涓嶇劧浼氬崱鍦≒opup灞傚綋鍓嶇殑Item涓�
+                this.Focus();
+            }
+            if (DataContext is MultiComboBoxData data)
+            {
+                data.IsChecked = !data.IsChecked;
+                e.Handled = true;
+            }
+        }
+
+        private void MultiComboBoxItem_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
+        {
+            if (e.OldValue != null && e.OldValue is MultiComboBoxData oldData)
+            {
+                oldData.IsCheckedChanged -= DataIsCheckedChangedChange;
+            }
+            if (DataContext != null && DataContext is MultiComboBoxData newData)
+            {
+                newData.IsCheckedChanged += DataIsCheckedChangedChange;
+            }
+        }
+
+        private void DataIsCheckedChangedChange(object sender, bool isChecked)
+        {
+            parent.Item_IsCheckedChanged((MultiComboBoxData)sender, this, isChecked);
+        }
+    }
+
+    public class MultiComboBoxDataConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is IEnumerable<object> items)
+            {
+                return items.Select(item => new MultiComboBoxData(item, "DisplayName", "DataValue")).ToList();
+            }
+            return null;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            return value;
+        }
+    }
+
+    public class MultiComboBoxData : INotifyPropertyChanged
+    {
+        #region ...
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        protected void RaisePropertyChanged(string propertyName)
+        {
+            if (PropertyChanged != null)
+            {
+                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+            }
+        }
+        #endregion
+
+        public event EventHandler<bool> IsCheckedChanged;
+
+        private bool isChecked;
+
+        public bool IsChecked
+        {
+            get { return isChecked; }
+            set
+            {
+                isChecked = value;
+                RaisePropertyChanged("IsChecked");
+                IsCheckedChanged?.Invoke(this, value);
+            }
+        }
+        public string DisplayName
+        {
+            get => showName?.GetValue(Data).ToString();
+        }
+
+        public string DataValue
+        {
+            get => valueName?.GetValue(Data).ToString();
+        }
+
+        private PropertyInfo showName;
+        private PropertyInfo valueName;
+
+        public MultiComboBoxData(object data, string showName, string valueName)
+        {
+            this.Data = data;
+            this.showName = data.GetType().GetProperty(showName);
+            this.valueName = data.GetType().GetProperty(valueName);
+        }
+
+        public object Data { get; private set; }
+    }
+
+    /// <summary>
+    /// MultiCombox.xaml 鐨勪氦浜掗�昏緫
+    /// </summary>
+    public partial class MultiComboBox : ComboBox
+    {
+        public static readonly string[] splits = new string[] { ", " };
+
+        protected override DependencyObject GetContainerForItemOverride()
+        {
+            var item = new MultiComboBoxItem(this);
+            return item;
+        }
+
+        [Bindable(true)]
+        [Category("Appearance")]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        [Localizability(LocalizationCategory.NeverLocalize)]
+        public object SelectedValues
+        {
+            get
+            {
+                return GetValue(SelectedValuesProperty);
+            }
+            set
+            {
+                SetValue(SelectedValuesProperty, value);
+            }
+        }
+
+        public static readonly DependencyProperty SelectedValuesProperty =
+            DependencyProperty.RegisterAttached("SelectedValues", typeof(object), typeof(MultiComboBox),
+                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+
+
+        public void Item_IsCheckedChanged(MultiComboBoxData data, MultiComboBoxItem item, bool isChecked)
+        {
+            var selectedValues = SelectedValues?.ToString() ?? "";
+            var showNames = this.Text?.ToString() ?? "";
+            List<string> values = string.IsNullOrEmpty(selectedValues) ? new List<string>() :
+                selectedValues.Split(splits, StringSplitOptions.RemoveEmptyEntries).ToList();
+            List<string> names = string.IsNullOrEmpty(showNames) ? new List<string>() :
+                showNames.Split(splits, StringSplitOptions.RemoveEmptyEntries).ToList();
+            if (isChecked)
+            {
+                values.Add(data.DataValue);
+                names.Add(data.DisplayName);
+            }
+            else
+            {
+                values.Remove(data.DataValue);
+                names.Remove(data.DisplayName);
+            }
+            Text = string.Join(", ", names);
+            SelectedValues = string.Join(", ", values);
+        }
+    }
+}

--
Gitblit v1.9.1