[Ammy.4] Fare binding con Ammy
Nel post precedente abbiamo mosso i primi passi con WPF & MVVM sviluppato con Ammy. Abbiamo creato una view ed abbiamo visto come legare staticamente questa view con il suo viewmodel.
Ricordo che tutto il codice sorgente si trova su GitHub:
https://github.com/Brain-Sys/FsxLogger.Client
Adesso, come facciamo binding?
L’unica view con cui abbiamo a che fare è contenuta nel file LoginWindow.ammy. La UI è questa:
Un controllo TextBox ed un PasswordBox, seguiti poi da due Button per eseguire due comandi (uno effettua il login e l’altro annulla l’operazione, per cui l’applicazione WPF viene chiusa).
La TextBox è collegata alla proprietà Username del ViewModel.
TextBox { #Cell(0, 1), VerticalAlignment: Center, HorizontalAlignment: Stretch, Text: bind Username, Padding:"4" }
Notare l’uso del mixin Cell. La penultima riga effettua il binding. La sintassi è molto compatta.
Text : bind Username
Abbiamo utilizzato la keyword bind di Ammy. La proprietà del viewmodel va indicata senza virgolette né apici, semplicemente indicando il nome della proprietà, come faremmo con lo XAML.
Se dovessimo impostare ulteriori proprietà per fare il binding (Mode, UpdateSourceTrigger, StringFormat, NotifyOn*), allora la sintassi cambia leggermente. Si ragiona sempre in JSON:
Text: bind Username set [ Mode: TwoWay, UpdateSourceTrigger: PropertyChanged, IsAsync: true ]
Dopo il Set si indica un array di proprietà, ciascuna con il suo valore. Nel caso specifico, impostare Mode ed IsAsync non era necessario, l’ho fatto a solo scopo didattico.
Per quanto riguarda i due Button, il binding verso i Command è semplicemente espresso come:
Button { Content: "Login", Command: bind LoginCommand } Button { Content: "Cancel", Command: bind CancelLoginCommand }
Ovviamente LoginCommand e CancelLoginCommand sono due proprietà RelayCommand (stiamo utilizzando MvvmLightLibs) esposte dal viewmodel. Cliccando su ciascuno dei due bottoni, viene scatenato il Command corrispondente. Non ci interessa approfondire altro in questo contesto.
Risolvere il problema del binding sul controllo PasswordBox è un po’ più complicato, perchè la proprietà Password non è una DependencyProperty. E’ OT rispetto a questo post, ma lo risolveremo.
Altri tipi di binding
Vediamo adesso altre forme di binding. Parliamo di come poter impostare il focus sul primo controllo all’avvio della finestra, posizionandolo sul controllo PasswordBox.
Questa cosa si risolve con due passaggi:
- diamo un nome al controllo a cui vogliamo assegnare il focus
- utilizziamo la classe FocusManager
Risolviamo prima lo step (1).
PasswordBox { #Cell(1, 1), VerticalAlignment: Center, HorizontalAlignment: Stretch, Name: "focus" }
Il nome assegnato al controllo è focus. A questo punto andiamo ad utilizzare la seguente sintassi associata alla Window.
FocusManager.FocusedElement: bind from "focus"
Utilizziamo la keyword bind seguita da from, che ci permette di cambiare il Source dell’oggetto verso il quale stiamo effettuando il binding. La stringa successiva “focus” rappresenta il nome del controllo. Lo XAML generato dal codice Ammy qui sopra è il seguente:
<FocusManager.FocusedElement> <Binding ElementName="focus"/> </FocusManager.FocusedElement>
Sostanzialmente, quando utilizziamo la sintassi bind from seguito da una stringa tra virgolette, questa stringa viene considerata come ElementName, quindi il Source diventerà un controllo WPF.
Da adesso in poi, quando la Window verrà renderizzata sullo schermo, WPF assegnerà il focus automaticamente al controllo PasswordBox: l’utente potrà premere Invio e fare login.
Beh, cosa posso indicare dopo il “from” ?
Ammy permette di scrivere binding di questo tipo:
- bind Username from $viewmodel (comportamento predefinito, al punto che è possibile omettere from $viewmodel)
- bind XYZ from $this, equivalente a RelativeSource={RelativeSource Self}
- bind from $resource XYZ, equivalente a Source={StaticResource XYZ}
Per maggiori dettagli fate riferimento al sito ufficiale di Ammy.
Happy coding!
Pingback: [Ammy.5] Modifiche a runtime del codice | Technology Experience (Reborn 4)
Pingback: [Ammy.5] Modifiche a runtime del codice – Technology Experience (Reborn 5)