Articoli con tag DependencyProperty
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
WP7 & Silvelight CoerceValue in DepencencyProperty
Pubblicato da sierrodc in Silverlight, WP7 il aprile 3, 2011
Per chi, come me, non capisce il motivo delle divergenze (o meglio, di alcune divergenze) tra WPF e Silverlight, volevo segnalare Dr.Webb:
http://drwpf.com/blog/2010/05/05/value-coercion-for-the-masses/
Ottimo il video che esplica come configurare correttamente gli helper per consentire il CoerceValueCallback in Silverlight.
PS: come da titolo, dato che sto sviluppando su Windows Phone, aggiungo che la tecnica funziona anche su questo (magnifico) dispositivo.