using System;
using System.Windows;
using System.Windows.Controls;
namespace Developpez.Dotnet.Windows.Behaviors
{
///
/// Fournit des propriétés attachées pour ajouter des fonctionnalités à un ComboBox
///
public class ComboBoxBehavior
{
#region AutoFilter
#region Public attached properties
///
/// Renvoie la valeur de la propriété attachée AutoFilter pour l'objet spécifié
///
/// L'objet pour lequel on veut obtenir la valeur de la propriété
/// true si le filtrage est activé, false sinon
[AttachedPropertyBrowsableForType(typeof(ComboBox))]
public static bool GetAutoFilter(ComboBox comboBox)
{
return (bool)comboBox.GetValue(AutoFilterProperty);
}
///
/// Définit la valeur de la propriété attachée AutoFilter pour l'objet spécifié
///
/// L'objet pour lequel on veut définir la valeur de la propriété
/// true pour activer le filtrage, false pour le désactiver
public static void SetAutoFilter(ComboBox comboBox, bool value)
{
comboBox.SetValue(AutoFilterProperty, value);
}
///
/// Identifie la propriété attachée AutoFilter
///
public static readonly DependencyProperty AutoFilterProperty =
DependencyProperty.RegisterAttached(
"AutoFilter",
typeof(bool),
typeof(ComboBoxBehavior),
new UIPropertyMetadata(false, AutoFilterChanged)
);
private static void AutoFilterChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ComboBox combo = sender as ComboBox;
if (combo != null)
{
combo.DoWhenLoaded(() => SetTextChangedHandler(combo));
}
}
///
/// Renvoie la valeur de la propriété attachée FilterComparisonType pour l'objet spécifié
///
/// L'objet pour lequel on veut obtenir la valeur de la propriété
/// Le type de comparaison utilisé pour le filtrage
[AttachedPropertyBrowsableForType(typeof(ComboBox))]
public static StringComparison GetFilterComparisonType(ComboBox comboBox)
{
return (StringComparison)comboBox.GetValue(FilterComparisonTypeProperty);
}
///
/// Définit la valeur de la propriété attachée FilterComparisonType pour l'objet spécifié
///
/// L'objet pour lequel on veut définir la valeur de la propriété
/// Le type de comparaison à utiliser pour le filtrage
public static void SetFilterComparisonType(ComboBox comboBox, StringComparison value)
{
comboBox.SetValue(FilterComparisonTypeProperty, value);
}
///
/// Identifie la propriété attachée FilterComparisonType
///
public static readonly DependencyProperty FilterComparisonTypeProperty =
DependencyProperty.RegisterAttached("FilterComparisonType", typeof(StringComparison), typeof(ComboBoxBehavior), new UIPropertyMetadata(StringComparison.CurrentCultureIgnoreCase));
///
/// Renvoie la valeur de la propriété attachée FilterMemberPath pour l'objet spécifié
///
/// L'objet pour lequel on veut obtenir la valeur de la propriété
/// Le membre utilisé pour le filtrage
[AttachedPropertyBrowsableForType(typeof(ComboBox))]
public static string GetFilterMemberPath(ComboBox comboBox)
{
return (string)comboBox.GetValue(FilterMemberPathProperty);
}
///
/// Définit la valeur de la propriété attachée FilterMemberPath pour l'objet spécifié
///
/// L'objet pour lequel on veut définir la valeur de la propriété
/// Le membre à utiliser pour le filtrage
public static void SetFilterMemberPath(ComboBox comboBox, string value)
{
comboBox.SetValue(FilterMemberPathProperty, value);
}
///
/// Identifie la propriété attachée FilterMemberPath
///
public static readonly DependencyProperty FilterMemberPathProperty =
DependencyProperty.RegisterAttached("FilterMemberPath", typeof(string), typeof(ComboBoxBehavior), new UIPropertyMetadata(null));
#endregion
#region Private attached properties
private static bool GetGotTextInput(DependencyObject obj)
{
return (bool)obj.GetValue(GotTextInputPropertyKey.DependencyProperty);
}
private static void SetGotTextInput(DependencyObject obj, bool value)
{
obj.SetValue(GotTextInputPropertyKey, value);
}
private static readonly DependencyPropertyKey GotTextInputPropertyKey =
DependencyProperty.RegisterAttachedReadOnly("GotTextInput", typeof(bool), typeof(ComboBoxBehavior), new UIPropertyMetadata(false));
#endregion
private static void combo_Loaded(object sender, RoutedEventArgs e)
{
ComboBox combo = sender as ComboBox;
if (combo == null)
return;
combo.Loaded -= combo_Loaded;
if (combo.Template != null)
SetTextChangedHandler(combo);
}
private static void SetTextChangedHandler(ComboBox combo)
{
TextBox textBox = combo.Template.FindName("PART_EditableTextBox", combo) as TextBox;
if (textBox != null)
{
bool enabled = GetAutoFilter(combo);
if (enabled)
{
textBox.PreviewTextInput += textBox_PreviewTextInput;
textBox.TextChanged += textBox_TextChanged;
}
else
{
textBox.PreviewTextInput -= textBox_PreviewTextInput;
textBox.TextChanged -= textBox_TextChanged;
}
}
}
private static void textBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox == null)
return;
SetGotTextInput(textBox, true);
}
private static void textBox_TextChanged(object sender, RoutedEventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox == null)
return;
ComboBox combo = textBox.TemplatedParent as ComboBox;
if (combo == null)
return;
if (combo.IsTextSearchEnabled && GetGotTextInput(textBox))
{
SetGotTextInput(textBox, false);
return;
}
int selStart = textBox.SelectionStart;
int selLength = textBox.SelectionLength;
combo.IsDropDownOpen = true;
string text = textBox.Text.Substring(0, selStart);
// Restore selection that has been changed by opening the dropdown
textBox.Select(selStart, selLength);
combo.Items.Filter = GetFilter(combo, text);
}
private static Predicate