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
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Creare gruppi di client per Event Grid MQTT
Utilizzare Tailwind CSS all'interno di React: primi componenti
Creare una libreria CSS universale: Clip-path
Generare HTML a runtime a partire da un componente Razor in ASP.NET Core
Filtering sulle colonne in una QuickGrid di Blazor
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Miglioramenti nelle performance di Angular 16
Creare una libreria CSS universale: i bottoni
Creare un'applicazione React e configurare Tailwind CSS
Sfruttare i KeyedService in un'applicazione Blazor in .NET 8
Usare un KeyedService di default in ASP.NET Core 8
I più letti di oggi
- Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
- Eseguire script pre e post esecuzione di un workflow di GitHub
- Creare una libreria CSS universale: Cards
- Migliorare l'organizzazione delle risorse con Azure Policy