In questa breve serie di Post, utilizzeremo quanto finora sviluppato per iniziare a costruire un’interfaccia avanzata per la console del nostro servizio Windows, in modo da poter costruire i Job che gli faremo eseguire. In Questa prima parte porteremo in libreria il CloseableTabItem che abbiamo costruito nel precedente post e faremo un paio di modifiche interessanti, nel post successivo andremo a creare la User Interface per gestire i Job all’interno della console del servizio.
Portare in Libreria il controllo CloseableTabItem e il suo template
Abbiamo evidenziato le modifiche effettuate alla libreria di uso comune DnwBaseWpf per quanto realizzeremo nei post dedicati all’interfaccia utente per i Job. Vediamole in dettaglio:
- Abbiamo aggiunto la cartella Components in cui abbiamo copiato la classe CloseableTabItem.
- Abbiamo aggiunto la cartella Themes, in cui abbiamo copiato Generic.xaml dove si trova il nostro Template.
- Abbiamo inoltre fatto due aggiunte agli EditingCommands creati un paio di post fa e a Styles.xaml.
Vediamo in dettaglio le modifiche:
Nel CloseableTabItem abbiamo fatto alcune piccole modifiche per migliorarne la funzionalità, la prima è ovviamente la modifica del Namespace
namespace Dnw.Base.Wpf.Components { public class CloseableTabItem : TabItem
Per inserirlo nelle nostre librerie in modo corretto, Attenzione che è importante oppure ci troviamo stranezze quando lo useremo.
public string TabUniqueID { get { return (string)this.GetValue(TabUniqueIDProperty); } set { this.SetValue(TabUniqueIDProperty, value); } } public static readonly DependencyProperty TabUniqueIDProperty = DependencyProperty.Register( FLD_TabUniqueID, typeof(string), typeof(CloseableTabItem), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); public string CloseButtonTooltip { get { return (string)this.GetValue(CloseButtonTooltipProperty); } set { this.SetValue(CloseButtonTooltipProperty, value); } } public static readonly DependencyProperty CloseButtonTooltipProperty = DependencyProperty.Register( FLD_CloseButtonTooltip, typeof(string), typeof(CloseableTabItem), new FrameworkPropertyMetadata("Closes this Tab", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Abbiamo aggiunto poi al nostro CloseableTabItem due dependency property la prima, TabUniqueID ci servirà per poter identificare un Tab all’interno di una collection, questo perché utilizzeremo i CloseableTabItem come Child Windows per la nostra interfaccia utente, quindi in quasi tutte le occasioni sarà opportuno che lo stesso Job non venga aperto più volte e allo stesso modo la finestra del Manager dei Job non dovrà essere aperta più volte per questione di pulizia dell’interfaccia. Ecco che la possibilità di identificare i Tab aperti ci permetterà di gestire tutto questo senza dover usare per forza la property Name che ha sicuramente alcuni vincoli alla sua forma visto che viene utilizzata dal compilatore per i suoi scopi. Vedremo in dettaglio l’uso di questa property nel prossimo post.
La seconda dependency property CloseButtonTooltip l’abbiamo definita per permettere che il Tooltip da mostrare sul Close Button non sia, come era nel template esempio, hardcoded nel template stesso.
Vediamo che cosa abbiamo modificato nel Template per farlo funzionare nel nuovo environment e per agganciare la dependency property al tooltip:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Dnw.Base.Wpf.Components">
Prima modifica, anche in questo caso abbiamo modificato il namespace che aggancia la classe CloseableTabItem al template.
<Button x:Name="PART_Close" HorizontalAlignment="Center" Margin="3,0,3,0" VerticalAlignment="Center" Width="16" Height="16" DockPanel.Dock="Right" Style="{DynamicResource CloseableTabItemButtonStyle}" Path=CloseButtonTooltip, RelativeSource={RelativeSource TemplatedParent}}"> <Path x:Name="Path" Stretch="Fill" StrokeThickness="0.5" Stroke="#FF333333" Fill="#FF969696" Data="F1 M 2.28484e-007,1.33331L 1.33333,0L 4.00001,2.66669L 6.66667,6.10352e-005L 8,1.33331L 5.33334,4L 8,6.66669L 6.66667,8L 4,5.33331L 1.33333,8L 1.086e-007,6.66669L 2.66667,4L 2.28484e-007,1.33331 Z " HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </Button>
La seconda modifica, il Binding alla Dependency property del Tooltip del Button, quando si lavora con i template non è possibile un binding diretto, è sempre indispensabile indicare il Path, e soprattutto utilizzare la RelativeSoruce per specificare che il Path è relativo al controllo su cui il template è applicato (TemplatedParent).
Ultima modifica, non fondamentale ma utile al progresso delle nostre librerie riusabili, abbiamo aggiunto uno stile a Styles.xaml per modificare l’aspetto dei TextBlock utilizzati nella barra di stato delle finestre o dei controlli. Ecco la sua definizione:
<Style x:Key="Status" TargetType="{x:Type TextBlock}"> <Setter Property="Foreground" Value="#FF3a752a" /> <Setter Property="FontSize" Value="11pt" /> <Setter Property="Margin" Value="0,0,15,4" /> <Setter Property="TextWrapping" Value="Wrap" /> </Style>
E’ uno stile simile a quello indicato come Header, cambia solo il colore del testo che è Verde scuro.
Il codice del progetto di esempio relativo alle nuove librerie comuni è disponibile a questo link:
Per qualsiasi domanda, approfondimento, o curiosità, utilizzate pure il link alla form di contatto in cima alla pagina o il forum Microsoft Italia su cui rispondo regolarmente.