Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - [Visual Studio]Interfaccia grafica elaborata
Forum - C# / VB.NET - [Visual Studio]Interfaccia grafica elaborata - Pagina 2

Pagine: [ 1 2 3 4 5 ] Precedente | Prossimo
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 9:37
Giovedì, 25/04/2013
Ciao!

Solitamente quando si lavoro con WPF si utilizza il pattern MVVM (Model View ViewModel, http://en.wikipedia.org/wiki/Model_View_ViewModel).
In poche parole separi la View dalla logica(ViewModel) e dai dati(Model)...
nel tuo caso dovresti:
- crearti un viewmodel da applicare alla tua view,
- creare un model che rappresenti una row nella list,
- nel viewmodel istanzi una collection di item del tipo del model(che diventeranno gli item della lista),

es.

model
Codice sorgente - presumibilmente Delphi

  1. public class User
  2. {
  3.     public string Name { get; set; }
  4.     public string Surname { get; set; }
  5.     public int Age { get; set; }
  6. }



viewmodel
la classe ViewModelBase(o BaseViewModel ;) devo controllare ma non ne ho tempo) fa parte di una libreria che semplifica un po' il pattern
mvvm(la puoi installare da nuget -> http://nuget.org/packages/MvvmLight/)
Codice sorgente - presumibilmente C++

  1. public class ViewModel : ViewModelBase
  2. {
  3.     public List<User> Users { get; set; }
  4.  
  5.     public ViewModel()
  6.     {
  7.         Users = new List<User>();
  8.     }
  9.  
  10.     public void Save()
  11.     {
  12.          // qui poi puoi salvare come vuoi
  13.          SaveObject(Users);
  14.     }
  15. }



bene ora che hai anche il viewmodel manca solo la view:
Codice sorgente - presumibilmente Plain Text

  1. [...]
  2. <ListView ItemsSource="{Binding Users}">
  3.       <ListView.View>
  4.         <GridView>
  5.           <GridViewColumn Width="140" Header="Name"
  6.               DisplayMemberBinding="{Binding Name}"  />
  7.           <GridViewColumn Width="140" Header="Surname"  
  8.               DisplayMemberBinding="{Binding Surname}" />
  9.           <GridViewColumn Width="140" Header="Age"
  10.               DisplayMemberBinding="{Binding Age}" />
  11.         </GridView>
  12.       </ListView.View>
  13.     </ListView>
  14. [...]



ora non ti resta che applicare il viewmodel alla view:
Codice sorgente - presumibilmente C# / VB.NET

  1. // nel file di code behind della view nel costruttore
  2.  
  3. public MainWindow() : Window
  4. {
  5.     public MainWindow()
  6.     {
  7.         InitializeComponent();
  8.  
  9.         // ci sarebbero altri modi più "furbi" e meno da "spaghetti code" per passargli il viewmodel, tuttavia visto che si è all'inizio va benissimo
  10.         // anche così
  11.         this.DataContext = new ViewModel();
  12.     }
  13. }



ciao!! :k:

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 10:20
Giovedì, 25/04/2013
Ok grazie della spiegazione. Prima di leggere il tuo post ero arrivata a questo punto:
Codice sorgente - presumibilmente Plain Text

  1. <Window x:Class="Compilation_CD_WPF.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         Title="MainWindow" Height="350" Width="500" MinWidth="500" MinHeight="350">
  5.     <Window.Resources>
  6.         <DataTemplate x:Key="checkboxCell">
  7.             <CheckBox Foreground="{x:Null}" OpacityMask="{x:Null}" Margin="0" Background="{x:Null}"/>
  8.         </DataTemplate>
  9.     </Window.Resources>
  10.         <ListView x:Name="musicList" Grid.RowSpan="2" Grid.ColumnSpan="2">
  11.             <ListView.View>
  12.                 <GridView>
  13.                     <GridViewColumn Header="Check" Width="35"CellTemplate="{StaticResource checkboxCell}"/>
  14.                     <GridViewColumn Header="Lock" Width="35" CellTemplate="{StaticResource checkboxCell}"/>
  15.                     <GridViewColumn Header="File" Width="100" DisplayMemberBinding="{Binding Path=file}"/>
  16.                     <GridViewColumn Header="Titolo" Width="100" DisplayMemberBinding="{Binding Path=title}"/>
  17.                     <GridViewColumn Header="ID" Width="35" DisplayMemberBinding="{Binding Path=ID}"/>
  18.                 </GridView>
  19.             </ListView.View>
  20.         </ListView>
  21. </Window>


con model(che usavo ma non conoscevo la definizione)
Codice sorgente - presumibilmente Delphi

  1. class musicItem
  2.         {
  3.             public string file { get; set; }
  4.             public string title { get; set; }
  5.             public int ID { get; set; }
  6.         }


cosi creo facilmente nuove righe e dovrei anche essere in grado di leggerle, ma non sapevo come accedere ai checkbox
allora ho eliminato i template dei checkbox e ho ridefinito il model
Codice sorgente - presumibilmente Delphi

  1. class musicItem
  2.         {
  3.             public CheckBox check { get; set; }
  4.             public CheckBox locked { get; set; }
  5.             public string file { get; set; }
  6.             public string title { get; set; }
  7.             public int ID { get; set; }
  8.  
  9.             public musicItem()
  10.             {
  11.                 this.check = new CheckBox();
  12.                 this.check.IsChecked = true;
  13.             }
  14.         }


Cosi a logica funziona ma invece di mostrarmi il controllo mi esegue un to string dello stesso... mi trovo scritto al posto del checkbox "System.Windows.Controls.CheckBox Cntenuto: IsChecked:True"
Mi chiedo il perche XD
mi sapete aiutare?

PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 17:05
Giovedì, 25/04/2013
Ciao!
Allora prima di tutto un piccolo accorgimento...
Solitamente gli oggetti che fanno parte del Model dovrebbero essere degli oggetti POCO (http://en.wikipedia.org/wiki/Plain_Old_CLR_Object), ovvero
oggetti "puri" che non dipendono da niente e che che rappresentano il dato in se.
Quindi utilizzare il tipo "Checkbox" dentro alla definizione di un model è definibilie come "antipattern", il tipo
da utilizzare dovrebbe essere "bool". Utilizzando il checkbox nel model la tua implementazione dipende
dalle librerie wpf cosa opposta alla definizione di viewmodel, solo la view deve dipendere dalle librerie che usi
per la visualizzazione dei dati, il viewmodel ed il model devono essere indipendenti da qualunque libreria grafica.

il tuo model dovrebbe diventare:
Codice sorgente - presumibilmente C#

  1. class musicItem
  2.             {
  3.                 public bool check { get; set; }
  4.                 public bool locked { get; set; }
  5.                 public string file { get; set; }
  6.                 public string title { get; set; }
  7.                 public int ID { get; set; }
  8.      
  9.                 public musicItem()
  10.                 {
  11.                     this.check = new CheckBox();
  12.                     this.check.IsChecked = true;
  13.                 }
  14.             }



e nello xaml:
Codice sorgente - presumibilmente Plain Text

  1. <DataTemplate x:Key="checkboxLockCell">
  2.             <CheckBox IsChecked={Binding locked} Foreground="{x:Null}" OpacityMask="{x:Null}" Margin="0" Background="{x:Null}"/>
  3.         </DataTemplate>
  4. <DataTemplate x:Key="checkboxCheckCell">
  5.             <CheckBox IsChecked={Binding check} Foreground="{x:Null}" OpacityMask="{x:Null}" Margin="0" Background="{x:Null}"/>
  6.         </DataTemplate>



ciaociao :k::k:

PM Quote
Avatar
Dedalux (Member)
Pro


Messaggi: 103
Iscritto: 15/12/2010

Segnala al moderatore
Postato alle 23:31
Giovedì, 25/04/2013
Non vorrei contraddire tasx, ma non capisco il passo in cui scrive

Codice sorgente - presumibilmente C# / VB.NET

  1. public musicItem()
  2. {
  3.        this.check = new CheckBox();
  4.        this.check.IsChecked = true;
  5. }



quindi dico quello che so, riguardo ad MVVM, visto che se ne parla:

innanzitutto è essenziale che i ViewModels implementino INotifyPropertyChanged, che permette al motore di databinding di rilevare i cambiamenti e aggiornare il valore di tutte le proprietà in binding con la View.
Di solito si eredita da una classe astratta che implementa appunto INPC, cerca ObservableObject (molti implementano anche INotifyPropertyChanged, ma dipende dalle necessità..).

Quasi sempre questa classe è ereditata anche dai Models, dato che è molto probabile che vengano modificati, e sarà quindi necessario che eventuali ListViews o DataGrids aggiornino il contenuto.

Che si tratti di Model o di ViewModel, le proprietà saranno tipi base o derivati, ma nulla che abbia a che fare con la View. Uno dei principi di MVVM è la separazione dei ruoli, e il layer VM non deve sapere nulla della View, esiste a prescindere da chi andrà ad utilizzarlo.
IsChecked della tua checkbox, nello XAML, andrà bindata alla proprietà bool del DataContext, e si aggiornerà in base alla modalità di update, che di solito è TwoWay, quindi sia cambiamenti da codice che da View, ma dipende dal tipo della proprietà.

Ti da quell'errore perchè cerchi di bindare un oggetto di tipo CheckBox (di cui il VM non dovrebbe nemmeno conoscere l'esistenza) su IsChecked della tua CheckBox, che è invece di tipo bool.

Comunque, per aiutarti a conoscere MVVM, di cui non potrai più fare a meno, ti consiglio di leggere questi (http://community.visual-basic.it/Alessandro/archive/2010/0 ... articoli, che pur essendo MOLTO essenziali, spiegano abbastanza chiaramente il meccanismo.
Io avevo iniziato da quelli.

Se preferisci qualcosa di più completo ci sono:
http://www.codeproject.com/Articles/100175/Model-View-View ...
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

Se invece sei già a buon punto ti potrebbero interessare quest iargomenti:
Dependency Injection
Inversion Of Control
Factory Pattern
Mediator Pattern

Poi quando hai capito il meccanismo, come per tutti gli argomenti, c'è un oceano di argomenti più specifici e relativi mari di articoli.

Siccome l'argomento non è proprio immediato da comprendere, chiedi pure! :k::k:

Ultima modifica effettuata da Dedalux il 25/04/2013 alle 23:49
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 14:09
Venerdì, 26/04/2013
Innanzitutto grazie mille ad entrambi :-) Ho capito, almeno la parte di tasx XD comunque immaginavo che a quel punto il
Codice sorgente - presumibilmente C# / VB.NET

  1. public musicItem() {        this.check = new CheckBox();        this.check.IsChecked = true; }

fosse inutile :-)
Dedalux grazie della tua spiegazione, ma mi lascia ancora un po disorientato XD appena avrò modo di leggere i link che mi hai postato magari capirò bene il tuo post XD Grazieee

Edit:
Piccola domandina... se io volessi aggiungere un evento al controllo checkbox a livello di logica lo fare i cosi:
Codice sorgente - presumibilmente Plain Text

  1. <GridView>
  2.                     <GridViewColumn Header="Check" Width="35">
  3.                         <GridViewColumn.CellTemplate>
  4.                             <DataTemplate>
  5.                                 <CheckBox IsChecked="{Binding check}" Click="{Binding changeCheck}" Style="{StaticResource checkboxCell}"/>
  6.                             </DataTemplate>
  7.                         </GridViewColumn.CellTemplate>
  8.                     </GridViewColumn>
  9.                     <GridViewColumn Header="Lock" Width="35">
  10.                         <GridViewColumn.CellTemplate>
  11.                             <DataTemplate>
  12.                                 <CheckBox IsChecked="{Binding locked}" Click="{Binding changeLocked}" Style="{StaticResource checkboxCell}"/>
  13.                             </DataTemplate>
  14.                         </GridViewColumn.CellTemplate>
  15.                     </GridViewColumn>
  16.                     <GridViewColumn Header="File" Width="100" DisplayMemberBinding="{Binding file}"/>
  17.                     <GridViewColumn Header="Titolo" Width="100" DisplayMemberBinding="{Binding title}"/>
  18.                     <GridViewColumn Header="ID" Width="35" DisplayMemberBinding="{Binding ID}"/>
  19.                 </GridView>


Codice sorgente - presumibilmente C#

  1. class musicItem
  2.         {
  3.             public bool check { get; set; }
  4.             public bool locked { get; set; }
  5.             public string file { get; set; }
  6.             public string title { get; set; }
  7.             public int ID { get; set; }
  8.  
  9.             public void changeCheck(object sender, RoutedEventArgs e)
  10.             {
  11.                 Trace.WriteLine("change check");
  12.             }
  13.  
  14.             public void changeLocked(object sender, RoutedEventArgs e)
  15.             {
  16.                 Trace.WriteLine("change locked");
  17.             }
  18.         }


Ma viene generata un eccezione... mi sapete spiegare come mai? se si potessero implementare gli eventi come ho scritto io sarebbe troppo comodo XD

Ultima modifica effettuata da Roby94 il 26/04/2013 alle 15:24
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 20:49
Venerdì, 26/04/2013
Allora prima di tutto le scuse, nel codice che ti ho postato ho dimenticato di cancellare li istruzioni nel costruttore...

Allora gli oggetti model non dovrebbero contenere logica di business, ma dovrebbero essere solo dei POCO, la logica di business andrebbe implementata nel viewModel....

l'interfaccia InotifyPropertyChanged viene già gestita da questa libreria http://www.galasoft.ch/mvvm/, è sufficiente che tu estendi la classe ViewModelBase nel tuo viewModel e poi quando una property viene cambiata la notifichi così:

Codice sorgente - presumibilmente C++

  1. private int _propertyInt { get; set; }
  2. public int PropertyInt
  3. {
  4.     get
  5.     {
  6.        return _propertyInt;
  7.     }
  8.     set
  9.     {
  10.         _propertyInt = value;
  11.         RaisePropertyChanged("PropertyInt");
  12.     }
  13. }



ogni volta che la proprietà verra scritta tutti i binding legati ad essa verrano aggiornati....

comunque qui trovi un valido esempio: http://apuntanotas.codeplex.com/SourceControl/changeset/vi ...



per il discorso dei checkbox guarda qui -> http://stackoverflow.com/questions/9293226/how-to-bind-a-c ... viene fatto uso anche della libreria di cui ti parlavo prima(è molto famosa per quanto riguarda il MVVM)....


ciao!

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 21:46
Venerdì, 26/04/2013
Grazie veramente della pazienza, immagino quanto sia pesante la situazione per voi...
Capisco che non posso fare a meno di questa libreria e mi sottometto alla vostra esperienza...
PEro vi chiedo ancora un pochino di pazienza... Allora io ho il mio model che sarà
Codice sorgente - presumibilmente C#

  1. public class MusicItem
  2.     {
  3.         public bool check { get; set; }
  4.         public bool locked { get; set; }
  5.         public string file { get; set; }
  6.         public string title { get; set; }
  7.         public int ID { get; set; }
  8.     }


Che se ho capito bene non viene aggiornato con i dati reali presenti nel listview, correggetemi se sbaglio...
In tal caso ho bisogno di un model che si applica all intera listview che eredita la classe InotifyPropertyChanged che in caso di modifica dei valori a livello di listview "crea un evento" adesso però non avendo mai dovuto usare il model mi chiedo se potete spiegarmi come costituirlo e ancora più importante come implementarlo nel listview esistente..
Grazie in anticipo

Edit:
Chiedo scusa, rileggendo ora i vecchi post mi accorgo che quello che prima era arabo sta iniziando a diventare italiano per me e effettivamente c'è scritto quasi tutto....scusate...
Comunque ricapitolando sono a questo punto:
ListView
Codice sorgente - presumibilmente Plain Text

  1. <ListView x:Name="musicList" ItemsSource="{Binding musicItems}" Margin="10,10,10,5" Grid.RowSpan="2" Grid.ColumnSpan="2">
  2.             <ListView.View>
  3.                 <GridView>
  4.                     <GridViewColumn Header="Check" Width="35">
  5.                         <GridViewColumn.CellTemplate>
  6.                             <DataTemplate>
  7.                                 <CheckBox IsChecked="{Binding check}" Click="{Binding changeCheck}" Style="{StaticResource checkboxCell}"/>
  8.                             </DataTemplate>
  9.                         </GridViewColumn.CellTemplate>
  10.                     </GridViewColumn>
  11.                     <GridViewColumn Header="Lock" Width="35">
  12.                         <GridViewColumn.CellTemplate>
  13.                             <DataTemplate>
  14.                                 <CheckBox IsChecked="{Binding locked}" Style="{StaticResource checkboxCell}"/>
  15.                             </DataTemplate>
  16.                         </GridViewColumn.CellTemplate>
  17.                     </GridViewColumn>
  18.                     <GridViewColumn Header="File" Width="100" DisplayMemberBinding="{Binding file}"/>
  19.                     <GridViewColumn Header="Titolo" Width="100" DisplayMemberBinding="{Binding title}"/>
  20.                     <GridViewColumn Header="ID" Width="35" DisplayMemberBinding="{Binding ID}"/>
  21.                 </GridView>
  22.             </ListView.View>
  23.         </ListView>


Model
Codice sorgente - presumibilmente C#

  1. public class MusicItem
  2.     {
  3.         public bool check { get; set; }
  4.         public bool locked { get; set; }
  5.         public string file { get; set; }
  6.         public string title { get; set; }
  7.         public int ID { get; set; }
  8.     }


ViewModel
Codice sorgente - presumibilmente C++

  1. public class ViewMusic : ViewModelBase
  2.     {    
  3.         public List<MusicItem> musicItems { get; set; }
  4.  
  5.         public ViewMusic()
  6.         {
  7.             musicItems = new List<MusicItem>();
  8.         }
  9.     }


Inizializzazione
Codice sorgente - presumibilmente C# / VB.NET

  1. public MainWindow()
  2.         {
  3.             InitializeComponent();
  4.             this.musicList.DataContext = new ViewMusic();
  5.             this.musicList.Items.Add(new MusicItem());//Item di prova
  6.         }


Ora non capisco dove devo fare la verifica con InotifyPropertyChanged e se manca qualcosa per far funzionare il tutto

Ultima modifica effettuata da Roby94 il 26/04/2013 alle 22:44
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 23:23
Venerdì, 26/04/2013
Ciao!

Allora nel viewModel ti consiglio di usare al posto di
Codice sorgente - presumibilmente C# / VB.NET

  1. public List<MusicItem> musicItems { get; set; }


Codice sorgente - presumibilmente C# / VB.NET

  1. public ObservableCollection<MusicItem> musicItems { get; set; }



così i bindings vengono già notificati quando aggiungi o rimuovi qualcosa...

L'interfaccia INotifyPropertyChanged viene già implementata(o comunque gestita) da ViewModelBase, quindi non ti devi preoccupare di implementarla, l'importante è che quando una proprietà viene modificata tu chiami il metodo
Codice sorgente - presumibilmente Plain Text

  1. RaisePropertyChanged("NomeProprietà");


in tal modo i bindings riceveranno la notifica...


Il model che hai scritto va benissimo così ;), per i dati funziona così:
quando tu modifichi qualcosa sulla view che è bindato ad un model, la modifica viene rispecchiata sul model, mentre se modifichi qualcosa sul model devi notificarlo o con INotofyPropertyChanged o estendendo la classe ViewModelBase e chiamando il metodo RaisePropertyChanged...

in ultimo per rimanere in linea con il pattern i dati dovresti aggiungerli dal viewModel e non nel costruttore della finestra(View) 8-|8-| :rotfl:

ps: per il checkbox guardati il link del mio post precedente... ;)

PM Quote
Pagine: [ 1 2 3 4 5 ] Precedente | Prossimo