Articoli con tag Behavior
Selezionare il contenuto di una TextBox WPF al focus
Riporto qui la soluzione presentata da Donelle su stackoverflow con una piccola modifica.
Innanzitutto il link originale: http://stackoverflow.com/questions/660554/how-to-automatically-select-all-text-on-focus-in-wpf-textbox
La modifica consiste nell’includere il comportamento come un behavior. Ecco il codice:
public static class TextBoxBehaviors { public static void SetSelectOnFocus(UIElement element, Boolean value) { element.SetValue(SelectOnFocusProperty, value); } public static bool GetSelectOnFocus(UIElement element) { return (bool)element.GetValue(SelectOnFocusProperty); } public static readonly DependencyProperty SelectOnFocusProperty = DependencyProperty.RegisterAttached("SelectOnFocus", typeof(bool), typeof(TextBoxBehaviors), new FrameworkPropertyMetadata(false, SelectOnFocusPropertyChangedCallback)); private static void SelectOnFocusPropertyChangedCallback(DependencyObject depObj, DependencyPropertyChangedEventArgs eventArgs) { TextBox tb = depObj as TextBox; if (tb != null) { if ((bool)eventArgs.OldValue == false && (bool)eventArgs.NewValue == true) { //attach events tb.PreviewMouseLeftButtonDown += SelectivelyIgnoreMouseButton; tb.GotKeyboardFocus += SelectAllText; tb.MouseDoubleClick += SelectAllText; } else if ((bool)eventArgs.OldValue == true && (bool)eventArgs.NewValue == false) { //detach events tb.PreviewMouseLeftButtonDown -= SelectivelyIgnoreMouseButton; tb.GotKeyboardFocus -= SelectAllText; tb.MouseDoubleClick -= SelectAllText; } } } private static void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e) { DependencyObject parent = e.OriginalSource as UIElement; while (parent != null && !(parent is TextBox)) parent = VisualTreeHelper.GetParent(parent); if (parent != null) { var textBox = (TextBox)parent; if (!textBox.IsKeyboardFocusWithin) { textBox.Focus(); e.Handled = true; } } } private static void SelectAllText(object sender, RoutedEventArgs e) { var textBox = e.OriginalSource as TextBox; if (textBox != null) textBox.SelectAll(); } }
E’ possibile ora aggiungere nello xaml il comportamento aggiungendo il behavior:
<TextBox Text="Selezionami per provare" behaviors:TextBoxBehaviors.SelectOnFocus="True" />
Unselect DataGridRow in DataGrid
Oggi si è presentato il seguente problema:
Ho usato una griglia per applicare una sorta di filtro su un altro controllo in base alle DataGridRow selezionate; il cliente ha voluto che, cliccando fuori dalle colonne di una DataGrid, tutte le righe selezionate si deselezionassero (eliminando in questo modo il filtro).
L’unico modo navito per farlo è cliccare sulla DataGridRow selezionata tenendo premuto il tasto CTRL.
Ho quindi creato il codice qui sotto.
In pratica cliccando al di fuori delle colonne (parte destra della Griglia) si clicca su un elemento figlio di una DataGridRow ma non su un elemento figlio di una DataGridCell (si può vedere facilmente con WPF Inspector oppure con Snoop).
Testo quindi questa condizione e deseleziono tutto se verificata:
public static class DataGridBehaviors { public static bool GetUnselectOnClickOutside(DependencyObject obj) { return (bool)obj.GetValue(UnselectOnClickOutsideProperty); } public static void SetUnselectOnClickOutside(DependencyObject obj, bool value) { obj.SetValue(UnselectOnClickOutsideProperty, value); } public static readonly DependencyProperty UnselectOnClickOutsideProperty = DependencyProperty.RegisterAttached("UnselectOnClickOutside", typeof(bool), typeof(DataGridBehaviors), new UIPropertyMetadata(false, UnselectOnClickOutsidePropertyChangedCallback)); private static void UnselectOnClickOutsidePropertyChangedCallback(DependencyObject depObj, DependencyPropertyChangedEventArgs eventArgs) { DataGrid grid = depObj as DataGrid; if (depObj != null) { if ((bool)eventArgs.OldValue == false && (bool)eventArgs.NewValue == true) grid.MouseLeftButtonUp += AssociatedObjectUnselectOnClickOutside; else if ((bool)eventArgs.OldValue == true && (bool)eventArgs.NewValue == false) grid.MouseLeftButtonUp -= AssociatedObjectUnselectOnClickOutside; } } private static void AssociatedObjectUnselectOnClickOutside(object sender, MouseButtonEventArgs e) { DataGrid datagrid = e.Source as DataGrid; DependencyObject originalControl = e.OriginalSource as DependencyObject; DataGridCell cell; DataGridRow row; if (TryFindParent<DataGridRow>(originalControl, out row) && !TryFindParent<DataGridCell>(originalControl, out cell)) { datagrid.UnselectAll(); } } private static bool TryFindParent<T>(DependencyObject child, out T result) where T : class { Contract.Requires(child != null, "child could not be null"); Contract.Ensures(Contract.Result<bool>() == true && Contract.ValueAtReturn<T>(out result) != null && result is T, "Result found rule violated"); Contract.Ensures(Contract.Result<bool>() == false && Contract.ValueAtReturn<T>(out result) == null, "Result not found rule violated"); var parent = VisualTreeHelper.GetParent(child); result = parent as T; if (result != null) return true; else if (parent != null) return TryFindParent<T>(parent, out result); else return false; } }
Questo è un behavior applicabile ad ogni griglia tramite AttachedProperty:
<DataGrid ItemsSource=”{Binding}” local:DataGridBehaviors.UnselectOnClickOutside=”True” />
Et voilà! Les jeux sont faits