La ListBox è senza ombra di dubbio uno dei controlli più utilizzati di Silverlight, sia per le funzionalità, come la sincronizzazione con le collezioni che implementano ICollectionView, sia per la facilità con la quale è possibile impostarne l'aspetto.
Utilizzando le caratteristiche del Visual State Manager è possibile personalizzare, anche in maniera estrema, l'aspetto della ListBox. Ci sono però alcuni particolari, come il colore di Foreground, che è difficile personalizzare se non limitando la possibilità di riutilizzare la template.
È utile ricordare l'anatomia che determina l'aspetto si una ListBox: la proprietà ItemTemplate determina la template da utilizzare per visualizzare i dati, mentre ItemContainerStyle determina l'aspetto del contenitore.
Un modo per modificare la selezione ed il colore di Foreground di un ListBoxItem è modificarne la template, e sostituire il ContentPresenter con una TextBlock. Questa modifica è più che lecita, ma di fatto impedisce di utilizzare qualsiasi tipo di DataTemplate ed è poco riutilizzabile.
Per aggirare questo problema possiamo realizzare un semplice Behavior, creiamo quindi una nuova classe che estenda il tipo Behavior:
public class SetSelectedItemForegroundBehavior : Behavior<ListBox>{}
Abbiano assegnato al Typed Argument il tipo ListBox, questo limita l'utilizzo di questo behavior al tipo ListBox e tipizza fortemente la proprietà AssociatedObject che il tipo Behavior<T> espone.
Proseguiamo dichiarando un campo di tipo Brush, nel quale salveremo il colore corrente dell'elemento non ancora selezionato e una DependendyProperty per impostare il colore che deve assumere dopo la selezione.
private Brush originalBush; public Color SelectedColorProperty { get { return ( Color)GetValue(SelectedColorPropertyProperty); } set { SetValue(SelectedColorPropertyProperty, value); } }
Eseguiamo l'override del metodo OnAttached e registriamoci per l'evento SelectionChanged:
protected override void OnAttached() { base.OnAttached(); this.AssociatedObject.SelectionChanged += new SelectionChangedEventHandler(AssociatedObject_SelectionChanged); }
Il metodo è abbastanza semplice e si limita a recuperare l'elemento selezionato e ad impostarne il colore oltre a reimpostare il colore originale dell'elemento deselezionato:
protected override void OnAttached() { base.OnAttached(); this.AssociatedObject.SelectionChanged += new SelectionChangedEventHandler(AssociatedObject_SelectionChanged); } void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0) { if (e.AddedItems[0] is ListBoxItem) { ListBoxItem item = (ListBoxItem)e.AddedItems[0]; originalBush = item.Foreground; item.Foreground = new SolidColorBrush(SelectedColorProperty); } else { Action a = null; a = () => { ListBoxItem listBoxItem = AssociatedObject.ItemContainerGenerator.ContainerFromItem(e.AddedItems[0]) as ListBoxItem; if (listBoxItem != null) listBoxItem.Foreground = new SolidColorBrush(Colors.White); else Dispatcher.BeginInvoke(a); }; Dispatcher.BeginInvoke(a); } } if (e.RemovedItems.Count > 0) { if (e.RemovedItems[0] is ListBoxItem) { ((ListBoxItem)e.RemovedItems[0]).Foreground = originalBush; } else { Action a = null; a = () => { ListBoxItem listBoxItem = AssociatedObject.ItemContainerGenerator.ContainerFromItem(e.RemovedItems[0]) as ListBoxItem; if (listBoxItem != null) listBoxItem.Foreground = new SolidColorBrush(Colors.Black); else Dispatcher.BeginInvoke(a); }; Dispatcher.BeginInvoke(a); } } }
L'unica cosa particolare da notare è l'utilizzo di un ciclo per recuperare il ListBoxItem in caso la lista sia creata da DataBind piuttosto che da XAML. Questo espediente è necessario in quanto non è possibile determinare a priori quando il ListBoxItem verrà creato, poiché tutto il processo è asincrono.
Non ci resta che compilare il nostro Behavior e associarlo alla nostra ListBox, ed in seguito impostare il colore da associare all'elemento selezionato.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Copiare automaticamente le secret tra più repository di GitHub
Ottimizzazione dei block template in Angular 17
Hosting di componenti WebAssembly in un'applicazione Blazor static
Usare un KeyedService di default in ASP.NET Core 8
Sfruttare MQTT in cloud e in edge con Azure Event Grid
Effettuare il binding di date in Blazor
Sfruttare al massimo i topic space di Event Grid MQTT
Utilizzare la versione generica di EntityTypeConfiguration in Entity Framework Core
Utilizzare HiLo per ottimizzare le insert in un database con Entity Framework
Short-circuiting della Pipeline in ASP.NET Core
Visualizzare le change sul plan di Terraform tramite le GitHub Actions
Determinare lo stato di un pod in Kubernetes