using HMI.UI.Converter;
|
using HMI.UI.MDI;
|
using System;
|
using System.ComponentModel;
|
using System.Windows;
|
using System.Windows.Controls;
|
using System.Windows.Data;
|
using System.Windows.Input;
|
using System.Windows.Media;
|
|
namespace HMI.UI
|
{
|
public class TableComboBox : ItemsControl
|
{
|
static TableComboBox()
|
{
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(TableComboBox), new FrameworkPropertyMetadata(typeof(TableComboBox)));
|
}
|
|
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
|
"Value",
|
typeof(object),
|
typeof(TableComboBox),
|
new FrameworkPropertyMetadata());
|
|
public static readonly DependencyProperty CanEditProperty = DependencyProperty.Register(
|
"CanEdit",
|
typeof(bool),
|
typeof(TableComboBox),
|
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnCanEditPropertyChanged)));
|
|
public static DependencyProperty IsEditingProperty = DependencyProperty.Register(
|
"IsEditing",
|
typeof(bool),
|
typeof(TableComboBox),
|
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsEditingPropertyChanged)));
|
|
public static DependencyProperty PreEditingProperty = DependencyProperty.Register(
|
"PreEditing",
|
typeof(Func<bool?>),
|
typeof(TableComboBox),
|
new FrameworkPropertyMetadata());
|
|
public static DependencyProperty ShowEmptyProperty = DependencyProperty.Register(
|
"ShowEmpty",
|
typeof(bool),
|
typeof(TableComboBox),
|
new FrameworkPropertyMetadata(false));
|
|
public static DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register(
|
"IsDropDownOpen",
|
typeof(bool),
|
typeof(TableComboBox),
|
new FrameworkPropertyMetadata(false));
|
|
|
private static void OnCanEditPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
|
{
|
if (obj is TableComboBox eb && e.Property == CanEditProperty)
|
{
|
bool value = (bool)e.NewValue;
|
if (value)
|
{
|
eb.MouseDoubleClick += eb.EditBox_MouseDoubleClick;
|
}
|
else
|
{
|
eb.MouseDoubleClick -= eb.EditBox_MouseDoubleClick;
|
}
|
}
|
}
|
|
private static void OnIsEditingPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
|
{
|
if (obj is TableComboBox eb && e.Property == IsEditingProperty)
|
{
|
bool value = (bool)e.NewValue;
|
eb.editor.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
|
if (value)
|
{
|
eb.editor.Focus();
|
}
|
}
|
}
|
|
private ComboBox editor;
|
public TableComboBox()
|
{
|
this.Loaded += EditBox_Loaded;
|
}
|
|
public bool IsDropDownOpen
|
{
|
get => (bool)GetValue(IsDropDownOpenProperty);
|
set
|
{
|
SetValue(IsDropDownOpenProperty, value);
|
}
|
}
|
|
|
private void EditBox_Loaded(object sender, RoutedEventArgs e)
|
{
|
editor = this.Template.FindName("PART_ComboBoxPart", this) as ComboBox;
|
editor.DisplayMemberPath = this.DisplayMemberPath;
|
editor.SelectedValuePath = this.SelectedValuePath;
|
editor.ItemsSource = this.ItemsSource;
|
editor.SelectedValue = Value;
|
editor.SelectionChanged += Editor_SelectionChanged;
|
|
Binding binding = new Binding("IsDropDownOpen")
|
{
|
Source = this,
|
Mode = BindingMode.TwoWay,
|
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
|
};
|
editor.SetBinding(ComboBox.IsDropDownOpenProperty, binding);
|
}
|
|
private void Editor_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
{
|
ComboBox box = sender as ComboBox;
|
if (IsEditing)
|
{
|
box.Focus();
|
}
|
}
|
|
private void EditBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
{
|
if (IsEditing)
|
{
|
return;
|
}
|
|
Func<bool?> pre = GetValue(PreEditingProperty) as Func<bool?>;
|
if (pre != null && pre.Invoke() != true)
|
{
|
return;
|
}
|
//var win = Window.GetWindow(this);
|
|
//win.MouseDown += EditBox_LostFocus;
|
editor.LostFocus += EditBox_LostFocus;
|
IsEditing = true;
|
e.Handled = true;
|
}
|
|
public static bool GetElementUnderMouse(UIElement relativeTo, UIElement target)
|
{
|
Point mousePosition = Mouse.GetPosition(relativeTo);
|
bool res = false;
|
HitTestResultCallback resultCallback = (result) =>
|
{
|
// 获取相交的UI元素
|
var element = result.VisualHit as FrameworkElement;
|
|
if (element != null && element == target)
|
{
|
res = true;
|
return HitTestResultBehavior.Stop; // 找到后停止遍历
|
}
|
return HitTestResultBehavior.Continue;
|
};
|
|
VisualTreeHelper.HitTest(relativeTo, null,
|
resultCallback, new PointHitTestParameters(mousePosition));
|
return res;
|
}
|
|
private void EditBox_LostFocus(object sender, RoutedEventArgs e)
|
{
|
if (IsDropDownOpen)
|
{
|
return;
|
}
|
if (sender == editor)
|
{
|
IsEditing = false;
|
editor.LostFocus -= EditBox_LostFocus;
|
Window.GetWindow(this).MouseDown -= EditBox_LostFocus;
|
}
|
else
|
{
|
var win = sender as Window;
|
if (!GetElementUnderMouse(win, this))
|
{
|
//editing.Focu
|
IsEditing = false;
|
win.MouseDown -= EditBox_LostFocus;
|
Window.GetWindow(this).MouseDown -= EditBox_LostFocus;
|
}
|
}
|
}
|
|
public object Value
|
{
|
get
|
{
|
return GetValue(ValueProperty);
|
}
|
set
|
{
|
SetValue(ValueProperty, value);
|
}
|
}
|
|
public bool CanEdit
|
{
|
get => (bool)GetValue(CanEditProperty);
|
set
|
{
|
SetValue(CanEditProperty, value);
|
}
|
}
|
|
public string SelectedValuePath
|
{
|
get; set;
|
}
|
|
public bool IsEditing
|
{
|
get => (bool)GetValue(IsEditingProperty);
|
set
|
{
|
SetValue(IsEditingProperty, value);
|
}
|
}
|
|
public Func<bool?> PreEditing
|
{
|
get => (Func<bool?>)GetValue(PreEditingProperty);
|
set
|
{
|
SetValue(PreEditingProperty, value);
|
}
|
}
|
|
public bool ShowEmpty
|
{
|
get => (bool)GetValue(ShowEmptyProperty);
|
set
|
{
|
SetValue(ShowEmptyProperty, value);
|
}
|
}
|
}
|
}
|