using System;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Controls;
using System.Windows.Data;
namespace WPFluent.Controls
{
[TemplatePart(Name = FilterTextBox, Type = typeof(System.Windows.Controls.TextBox))]
[TemplatePart(Name = "PART_EditableTextBox", Type = typeof(System.Windows.Controls.TextBox))]
public class ComboBoxEx : ComboBox
{
private const string FilterTextBox = "PART_FilterTextBox";
// Using a DependencyProperty as the backing store for FilterBoxPlaceholderText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FilterBoxPlaceholderTextProperty = DependencyProperty.Register(
nameof(FilterBoxPlaceholderText),
typeof(string),
typeof(ComboBoxEx),
new PropertyMetadata("输入关键字"));
public static readonly DependencyProperty HeaderPlacementProperty = DependencyProperty.Register(
nameof(HeaderPlacement),
typeof(Dock),
typeof(ComboBoxEx),
new PropertyMetadata(Dock.Top));
// Using a DependencyProperty as the backing store for Header. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
nameof(Header),
typeof(string),
typeof(ComboBoxEx),
new PropertyMetadata(null));
public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register(
nameof(PlaceholderText),
typeof(string),
typeof(ComboBoxEx),
new PropertyMetadata("请选择..."));
public static readonly DependencyProperty ShowFilterBoxProperty = DependencyProperty.Register(
nameof(ShowFilterBox),
typeof(bool),
typeof(ComboBoxEx),
new PropertyMetadata(true));
private System.Windows.Controls.TextBox filterTextBox;
private ICollectionView view;
static ComboBoxEx()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(ComboBoxEx),
new FrameworkPropertyMetadata(typeof(ComboBoxEx)));
}
///
/// 过滤搜索
///
///
///
private void PART_FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (filterTextBox == null)
return;
if (view != null)
{
view.Filter += (o) =>
{
if (o is string)
{
var value = o.ToString().ToLower();
return value.IndexOf(filterTextBox.Text.ToLower(), StringComparison.Ordinal) != -1;
}
else
{
var obj = GetPropertyValue(o, DisplayMemberPath);
//在xaml中写入Combobox时
if (obj is ComboBoxItem item)
{
obj = item.Content;
}
var value = Convert.ToString(obj).ToLower();
return value.IndexOf(filterTextBox.Text.ToLower(), StringComparison.Ordinal) != -1;
}
};
}
}
///
/// 获取view
///
///
/// 适用于在xaml中添加ComboBoxItem的情况
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
view = CollectionViewSource.GetDefaultView(Items);
}
///
/// 获取view
///
///
///
/// 适用于绑定ItemsSource
protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
base.OnItemsSourceChanged(oldValue, newValue);
view = CollectionViewSource.GetDefaultView(ItemsSource);
}
///
/// 获取属性,若无法获取则返回源对象
///
public static object GetPropertyValue(object obj, string path)
{
if (obj == null)
return string.Empty;
var result = obj;
if (!string.IsNullOrEmpty(path))
{
var property = obj.GetType().GetProperty(path);
if (property != null)
{
try
{
result = property.GetValue(obj, null);
return result;
}
catch
{
try
{
var type = obj.GetType();
var mInfo = type.GetMethod($"get_{path}");
if (mInfo != null)
{
result = mInfo.Invoke(obj, null);
return result;
}
}
catch
{
}
}
}
}
return result;
}
///
/// 应用样板
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (filterTextBox != null)
{
filterTextBox.TextChanged -= PART_FilterTextBox_TextChanged;
}
filterTextBox = GetTemplateChild(FilterTextBox) as System.Windows.Controls.TextBox;
if (filterTextBox != null)
{
filterTextBox.TextChanged += PART_FilterTextBox_TextChanged;
}
}
[Category("自定义"), Bindable(true, BindingDirection.OneWay), Description("搜索框水印")]
public string FilterBoxPlaceholderText
{
get { return (string)GetValue(FilterBoxPlaceholderTextProperty); }
set { SetValue(FilterBoxPlaceholderTextProperty, value); }
}
[Category("自定义"), Bindable(true, BindingDirection.TwoWay), Description("标题")]
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
//public bool PlaceholderEnable
//{
// get { return (bool)GetValue(PlaceholderEnableProperty); }
// set { SetValue(PlaceholderEnableProperty, value); }
//}
//// Using a DependencyProperty as the backing store for PlaceholderEnable. This enables animation, styling, binding, etc...
//public static readonly DependencyProperty PlaceholderEnableProperty = DependencyProperty.Register(
// nameof(PlaceholderEnable),
// typeof(bool),
// typeof(ComboBoxEx),
// new PropertyMetadata(true)
//);
[Category("自定义"), Bindable(true, BindingDirection.OneWay), Description("标题位置")]
public Dock HeaderPlacement
{
get { return (Dock)GetValue(HeaderPlacementProperty); }
set { SetValue(HeaderPlacementProperty, value); }
}
///
///
///
///
/// 特性含义:属性面板(支持分组,支持数据绑定,支持属性提示)
/// [Category("自定义分组"),Bindable(true,BindingDirection.OneWay),Description("选择框水印")]
///
[Category("自定义"), Bindable(true, BindingDirection.OneWay), Description("选择框水印")]
public string PlaceholderText
{
get { return (string)GetValue(PlaceholderTextProperty); }
set { SetValue(PlaceholderTextProperty, value); }
}
///
/// 获取或者设置下拉列表过滤文本框的显示与隐藏
///
[Category("自定义"), Bindable(true, BindingDirection.OneWay), Description("过滤框")]
public bool ShowFilterBox
{
get => (bool)GetValue(ShowFilterBoxProperty);
set { SetValue(ShowFilterBoxProperty, value); }
}
}
}