Autore Topic: Definizione Gui "dall'esterno"  (Letto 1852 volte)

Offline Allanon

  • Administrator
  • Synthetic Voodoo
  • *****
  • Post: 3498
  • Karma: +17/-4
    • Mostra profilo
    • http://www.a-mc.biz
Definizione Gui "dall'esterno"
« il: 06 Agosto 2011, 18:15:46 »
Sto riscrivendo la mia scuilib (un modulo per le Gui sotto Hollywood e quindi 100℅ platform indipendent) con ottimi risultati di performance grazie ad un po' di esperienza acquisita con il lavoro originale e mi stava prendendo l'idea di supportare la definizione delle gui  dall'esterno.
So che generalmente vengono usati file xml  per descrivere le gui  e mi chiedevo se qualcuno di voi può indirizzarmi a della documentazione dove siano descritti degli standard, se esistono, ma penso proprio di si  :D
Creare un'applicazione con la possibilità di definire la gui a prescindere dall'eseguibile compilato credo che sia decisamente interessante come feature  :D
In questo modo risulta anche molto semplice creare delle gui "scalabili" in complessità senza bisogno di ricompilare alcunché.

Si accettano suggerimenti  e idee  :geek:
« Ultima modifica: 01 Gennaio 1970, 02:00:00 da Guest »

Offline cdimauro

  • Human Debugger
  • *****
  • Post: 4291
  • Karma: +7/-95
    • Mostra profilo
Re: Definizione Gui "dall'esterno"
« Risposta #1 il: 06 Agosto 2011, 20:10:21 »
Io uso XAML per sviluppare l'interfaccia grafica dell'applicazione che sto scrivendo per Windows Phone 7, e ti posso assicurare che è una goduria immensa anche soltanto lavorare di XML (poi è possibile farlo anche da VisualStudio, e ancora meglio con Expression Blend).

XAML si usa anche per sviluppare applicazioni desktop o web con Silverlight, che a sua volta deriva da Windows Presentation Foundation.

Se riesci a implementare XAML o un suo sottoinsieme per definire le GUI di Hollywood poi potrai benissimo usare tutti gli strumenti Microsoft per disegnarle, senza aver bisogno di creare un'applicazione tu.

P.S. Uno dei miei sogni nel cassetto è di fare tutto ciò per Python.

Offline Allanon

  • Administrator
  • Synthetic Voodoo
  • *****
  • Post: 3498
  • Karma: +17/-4
    • Mostra profilo
    • http://www.a-mc.biz
Re: Definizione Gui "dall'esterno"
« Risposta #2 il: 06 Agosto 2011, 21:10:19 »
Grazie della dritta  :P
Mi documento e vedo cosa posso fare, certo che l'idea di poter utilizzare tutti questi tool che hai mensionato mi stuzzica molto  :D
« Ultima modifica: 01 Gennaio 1970, 02:00:00 da Guest »

Offline Allanon

  • Administrator
  • Synthetic Voodoo
  • *****
  • Post: 3498
  • Karma: +17/-4
    • Mostra profilo
    • http://www.a-mc.biz
Re: Definizione Gui "dall'esterno"
« Risposta #3 il: 06 Agosto 2011, 21:55:38 »
Ho dato una rapida occhiata su msdn e non mi sembra nulla di impossibile da implementare, tuttavia ho alcuni dubbi che forse puoi aiutarmi a chiarire  :)

Faccio un esempio reale per esporre meglio i miei dubbi.

Diciamo che voglio creare un file manager (tanto per dirne una a casaccio) con tre sezioni ben distinte di cui una per la gestione dei file in locale, una per la gestione di file in remoto e una per le preferenze del programma.
E' possibile creare dei vincoli nella definizione della gui per cui sia vietato "mischiare" gli elementi della gui di una sezione con una altra?

Così a naso mi sembra che debba gestire questa possibilità dall'interno del programma, ossia quando carico la definizione della gui il programma la analizza e la convalida prima di crearla...

Scusa ma è la prima volta che mi addentro in questi campo e molto probabilmente starò dicendo delle castronerie :)
« Ultima modifica: 01 Gennaio 1970, 02:00:00 da Guest »

Offline cdimauro

  • Human Debugger
  • *****
  • Post: 4291
  • Karma: +7/-95
    • Mostra profilo
Re: Definizione Gui "dall'esterno"
« Risposta #4 il: 07 Agosto 2011, 07:24:19 »
Il tuo dubbio è legittimo e trova la risposta nei cosiddetti "binding" di XAML.

Il concetto del binding è quello di legare una specifica proprietà di un widget a una di un oggetto qualsiasi (quindi anche non di un elemento grafico. Immagina di legare il testo di un TextBlock a una proprietà, ovviamente di tipo string, di una classe della tua applicazione, in modo da farla visualizzare ogni qual volta essa cambi programmaticamente), e questo anche in maniera bidirezionale (il cambiamento dell'una aggiorna l'altra, e viceversa).

Per rientrare nel tuo discorso, faccio un esempio pratico. Ho due widget, un TextBox che contiene il path corrente, e subito alla sua destra c'è un Button con la lente d'ingrandimento che devono essere visualizzati entrambi assieme oppure nascosti sempre assieme. Per "legarne" la visibilità, si procede in questo modo in XAML:
Codice: [Seleziona]
<TextBox x:Name="CurrentPath" Visibility={Binding ElementName=SearchPath, Path=Visibility, Mode=TwoWay} />
<Button x:Name="SearchPath">
    <Image Source="Images/SearchIcon.png" />
</Button>
Come vedi è sufficiente specificare il binding una sola volta, perché il sistema provvederà poi a legare i due widget tramite le rispettive proprietà. Nello specifico, il binding afferma questo: la proprità Visibility di CurrentPath è legata alla proprietà Visibility di SearchPatch bidirezionalmente. Se fosse omesso l'attributo Mode, sarebbe ovviamente monodirezionale (CurrentPath.Visibility riflettere soltanto i cambiamenti di SearchPath.Visibility, e non il viceversa).

Se i tipi delle proprietà da legare non dovessero coincidere, XAML dà la possibilità di utilizzare un "convertitore", cioè una classe che si occupa di eseguire delle operazioni sul valore della proprietà a cui siamo legati, in modo da "trasformarlo" prima di assegnarlo alla nostra proprietà.

Immagina che la tua classe principale a cui è legata la pagina della tua interfaccia grafica (Silverlight organizza la GUI in "pagine" indipendenti; immagina che sia l'equivalente di un "form") esponga la proprietà booleana IsRemote che indica se si sta lavorando in remoto, e che in base a questo valore uno o più widget debbano essere visibili oppure no.

La proprietà Visibility è un enumerativo, per cui non puoi assegnarle un booleano. Si ricorre, quindi, a un comunissimo e strausato convertitore (che ti riporto in C#, ma è semplice da capire):
Codice: [Seleziona]
class BooleanToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
                return (bool) value ? Visibility.Visible : Visibility.Collapsed;
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
                return null;
        }
    }
Il metodo Convert è quello che c'interessa, e che fa un lavoro semplicissimo, come vedi. value è il valore che gli viene passato, e che sicuramente è un booleano nel nostro caso (siamo noi a "passarglielo"), che provvediamo a "castare" in bool. Dopodiché, in base al valore di verità, restituiamo l'enumerativo appropriato.
ConvertBack dev'essere implementato per forza, ma non c'interessa e restituiamo semplicemente null. Si usa per i convertitori bidirezionali, quando dall'enumerativo bisogna restituire il booleano.

Adesso mettiamo che vogliamo visualizzare un widget in base alla proprietà IsRemote di cui sopra. Ecco un estratto dello XAML:
Codice: [Seleziona]
<phone:PhoneApplicationPage
    x:Class="FileManagerPage" Name="this" />

    <phone:PhoneApplicationPage.Resources>
        <local:BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
    </phone:PhoneApplicationPage.Resources>

    <Button Content="Refresh" Visibility="{Binding ElementName=this, Path=IsRemote, Converter={StaticResource BooleanToVisibility}}" Click="OnRemoteResourcesRefreshClick" />

</phone:PhoneApplicationPage>
Da notare che fra le risorse della pagina ho dovuto dichiarare il convertitore in oggetto. Per il resto, tutto si risolve nel binding, come abbiamo visto prima, a cui viene semplicemente aggiunta la proprietà Converter che specifica la risorsa da utilizzare per la conversione.

Alla pagina abbiamo assegnato il nome "this", che rappresenta l'istanza della classe della GUI (che è quella che poi espone la proprietà IsRemote). Il nome può essere qualunque, ma si usa this per convenzione. Successivamente vien referenziato in ElementName.

Nel caso in cui dovessimo visualizzare in maniera mutuamente esclusiva widget legati a IsRemote, e altri alla sua negazione, le strade possibili sono due. La prima è che si crea un convertitore come quello di prima, che funziona in logica negata: serve a nascondere un oggetto se il booleano è vero, e viceversa. La seconda, che è quella che scelgo io, è quella di esporre la proprietà complementare di IsRemote, che chiamiamo ad esempio IsLocal, ed eseguire il binding degli altri widget a questa.

Per adesso finisco qui, ma aggiungo qualche considerazione. XAML può sembrare complicato a un primo approccio, perché si tratta di un modello abbastanza diverso da quello a cui magari siamo abituati. Ma una volta cominciato a lavorarci si apprezza la notevole potenza espressiva (nonché comodità!) del pattern Model View ViewModel su cui è basato (che deriva dal pattern Model View Presenter, a sua volta derivato dal più noto Model View Controller).

La cosa intrigante è che puoi definire con XAML tantissima roba che normalmente richiederebbe codice con un altro modello (chi ha sviluppato con Android sa cosa voglio dire!), e al contempo disaccoppiando moltissimo lo sviluppo dell'interfaccia grafica da quello del codice.

In generale io parto da XAML per definire la GUI, e quando poi serve costruisco quel poco di codice funzionale alla GUI stessa. In particolare scrivo molti converter perché mi permettono di realizzare cose molto carine, e faccio uso di "data binding" in modo da "popolare" automaticamente i widget con dei dati in maniera molto semplice ed efficace.

Il mio personalissimo problema è che una volta assaggiato XAML, lavorare con altro mi deprime.

Offline Allanon

  • Administrator
  • Synthetic Voodoo
  • *****
  • Post: 3498
  • Karma: +17/-4
    • Mostra profilo
    • http://www.a-mc.biz
Re: Definizione Gui "dall'esterno"
« Risposta #5 il: 07 Agosto 2011, 08:47:29 »
Grazie cdimauro, hai spiegato tutto molto bene, credo di aver capito però ho un'altro paio di dubbi:

1. Volevo chiederti se XAML prevede la definizione delle gui "al volo" in modo dinamico per customizzare le interfacce una volta compilato il codice. Da quello che ho capito usando XAML questo poi viene compilato assieme al sorgente del programma e "incorporato" nell'eseguibile finale. Sarebbe bello se l'applicazione una volta compilata fosse in grado di leggere un file XAML e generare la gui come descritta "sul momento". Con la stessa applicazione si potrebbero avere svariati layout completamente customizzabili.
Ma forse sto dicendo cose che in realtà XAML già prevede :P

2. Nel caso in cui il primo punto sia possibile, come posso realizzare un binding per elementi non propriamente legati tra loro da una proprietà?

Ti faccio un esempio:
mettiamo che io abbia un'applicazione con due finestre, come posso impedire che un oggetto progettato per la finestra 1 venga definito e visualizzato nella finestra 2?


Grazie per le preziosissime informazioni
:)
« Ultima modifica: 01 Gennaio 1970, 02:00:00 da Guest »

Offline cdimauro

  • Human Debugger
  • *****
  • Post: 4291
  • Karma: +7/-95
    • Mostra profilo
Re: Definizione Gui "dall'esterno"
« Risposta #6 il: 07 Agosto 2011, 09:05:12 »
1) E' già così. Gli XAML possono benissimo essere caricati, ma anche creati, al volo.

2) Il binding avviene sempre tramite proprietà (le property di C#, Delphi.NET, Python, e altri linguaggi). Puoi comunque eseguirlo anche a livello di codice, in qualsiasi momento. XAML ti dà semplicemente la comodità di farlo nell'XML, senza dover scrivere "papiri" di codice (Android-like).

3) Se per oggetto intendi un widget (o controllo grafico in generale), questo può avere un solo parent, ma puoi usarlo dove vuoi, anche in finestre diverse (ma soltanto in una alla volta). Se invece intendi un oggetto in generale, come ad esempio la fonte di dati da cui attingere tramite i data binding, non puoi impedire che venga utilizzato in altre finestre oltre a quella che hai progettato, perché per essere "agganciabili" (bindable) dai widget le property devono sempre essere "pubbliche", quindi "visibili" dall'esterno della classe in cui sono definite.

D'altra parte non vedo perché dovresti vincolare per forza l'uso di un oggetto con una sola finestra. Gli oggetti sono componenti di uso generale, sono riutilizzabili per definizione, ma, a parte questo, sei tu che definisci la GUI e quindi associ un oggetto a una finestra.

Diciamo che non ne capisco l'utilità, ma magari è un mio limite perché non conosco le tue esigenze.

Offline Allanon

  • Administrator
  • Synthetic Voodoo
  • *****
  • Post: 3498
  • Karma: +17/-4
    • Mostra profilo
    • http://www.a-mc.biz
Re: Definizione Gui "dall'esterno"
« Risposta #7 il: 07 Agosto 2011, 09:27:46 »
Per i punti 1 e 2: ottimo :)

Per quanto riguarda il discorso oggetti io intendo oggetti della gui quindi pulsanti, listview, label e via dicendo...
Ma mi hai chiarito il dubbio subito perchè nel codice sono io che definisco un elemento della gui come child di una determinata finestra pertanto se a runtime il mio programma carica una definizione di una interfaccia in XAML che definisce un elemento non definito per quella finestra già avrei un errore... si si, tutto chiaro adesso  :D
« Ultima modifica: 01 Gennaio 1970, 02:00:00 da Guest »

Tags: