Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Interact to mainWindow ListView

Îåêßíçóå áðü ôï ìÝëïò StrouMfios. Τελευταία δημοσίευση από το μέλος KelMan στις 30-01-2011, 21:20. Υπάρχουν 11 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  30-01-2011, 13:47 62792

    Interact to mainWindow ListView

    Καλησπέρα σε όλους,

    προσπαθώ να φτιάξω ένα μικρό πρόγραμμα σε wpf για λόγους πρακτικής και μόνο.
    Αυτό που θέλω να κάνω είναι μια ToDoList η οποία θα έχει στο mainWindow όλα τα items σε ένα ListView. 
    Στο mainWIndow  θα έχει και ένα button το οποίο θα ανοίγει ένα window(addNewItemWindow) στο οποίο θα γίνεται εισαγωγή νέου item.
    Μέχρι στιγμής η υλοποίηση έχει γίνει με το MVVM pattern και Entity Framework. 

    Ερώτηση
    Πως μπορώ από το addNewItemWindow με το πάτημα του κουμπιού save να εμφανίζεται το item στο ListView του mainWindow? 
    Γενικότερα ψάχνω έναν τρόπο με τον οποίο να μπορώ να ανανεώνω την ListView από οποιοδήποτε σημείο του application.

    Ευχαριστώ

    αν δεν το θες, www.antallakseto.gr
  •  30-01-2011, 14:10 62793 σε απάντηση της 62792

    Απ: Interact to mainWindow ListView

    Δεν ξέρω αν έχει καμία διαφορά με τα winforms, αλλά αν θες να έχεις πρόσβαση σε control από οπουδήποτε, πάνε στο modifier του και από private κάντο internal.

    Βέβαια ο πιο ορθόδοξος τρόπος είναι η δεύτερη φόρμα να έχει κάποιο property που να επιστρέφει το item που θέλεις και να το διαχειρίζεται μετά η μαμά φόρμα πχ κάτι αντίστοιχο σαν το DialogResult.

    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  30-01-2011, 16:50 62795 σε απάντηση της 62792

    Απ: Interact to mainWindow ListView

    Τυπικά το mainWindow και το addNewItemWindow θα πρέπει να είναι binded το καθένα στο δικό του ViewModel. Όπερ σημαίνει ότι το ListView σε κάθε ένα View θα πρέπει να είναι binded στο αντίστοιχο collection property του ViewModel. Άρα το μόνο που χρειάζεται είναι να ενημερώσεις το collection του main ViewModel για τα νέα items που υπάρχουν στο collection του addNewItem ViewModel.

    Τώρα, το πώς θα το κάνεις αυτό εξαρτάται από τον τρόπο που έχεις υλοποιήσει το switching ανάμεσα στα Views. Στις απλές περιπτώσεις υπάρχει η τεχνική των sub-ViewModels (υπάρχει ένα κεντρικό το οποίο συντονίζει όλα υπόλοιπα), μπορεί να έχεις υλοποιήσει το Locator pattern ή να έχεις χρησιμοποιήσει κάποιο framework (πχ Ocean, Prism, κλπ). Εσύ πώς το έχεις κάνει;

     


    Vir prudens non contra ventum mingit
  •  30-01-2011, 16:57 62796 σε απάντηση της 62795

    Απ: Interact to mainWindow ListView

    Ακόμα δεν έχω χρησιμοποιήσει κάποιο απο αυτά που μου ανέφερες.
    Δέν ήξερα με ποιόν τρόπο μπορεί να γίνει κάτι τέτοιο, αλλα τώρα θα ψάξω για το prism ώστε να το εφαρμόσω στο app.

    Το INotifyPropertyChanged παίζει κάοιο ρόλο σε αυτό που προσπαθώ να κάνω?

    αν δεν το θες, www.antallakseto.gr
  •  30-01-2011, 17:17 62797 σε απάντηση της 62796

    Απ: Interact to mainWindow ListView

    To Prism δεν είναι εύκολο και σίγουρα δεν πρέπει να πάρεις την απόφαση να το χρησιμοποιήσεις επειδή απλά το ανέφερα στην απάντησή μου. Θα είναι σαν να χρησιμοποιείς ένα τριαξονικό για να πας μέχρι το περίπτερο. Πριν βιαστείς με το Prism καλύτερα να πεις πώς έχεις υλοποιήσει το να βγαίνει η φόρμα του addNew μέσα από την Main.

     


    Vir prudens non contra ventum mingit
  •  30-01-2011, 17:41 62798 σε απάντηση της 62797

    Απ: Interact to mainWindow ListView

    Παρακάτω παραθέτω τον κώδικα

    MainWindow.xaml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    <Window x:Class="ToDoListTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:ToDoListTest.ViewModels"
            Title="MainWindow" Height="350" Width="525">
        
        <Window.DataContext>
            <local:MainWindowViewModel />
        </Window.DataContext>
        
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="133*" />
                <ColumnDefinition Width="370*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="60*" />
                <RowDefinition Height="251*" />
            </Grid.RowDefinitions>
            <ListView Grid.Row="1" Height="239" HorizontalAlignment="Left" Margin="12,0,0,0" Name="ToDoItemsLV" VerticalAlignment="Top" Width="479" Grid.ColumnSpan="2" ItemsSource="{Binding ItemResults}">
                <ListView.View>
                    <GridView>
                        </GridViewColumn Width="100" Header="Name" DisplayMemberBinding="{Binding Path=Name}">
                        </GridViewColumn Width="200" Header="Description" DisplayMemberBinding="{Binding Path=Description}">
                        </GridViewColumn Width="100" Header="Date To Act" DisplayMemberBinding="{Binding Path=DateToAct}">
                        </GridViewColumn Width="50" Header="Status" DisplayMemberBinding="{Binding Path=Status}">
                    </GridView>
                </ListView.View>
            </ListView>
            </Button Content="Add New Item" Width="100" Height="30" Margin="0,15,16,15" HorizontalAlignment="Right" Command="{Binding AddNewItem}">
        </Grid>
    </Window>


    AddItems.Xaml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    <Window x:Class="ToDoListTest.AddItems"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Add New Item" Height="340" Width="300"
            xmlns:local="clr-namespace:ToDoListTest.ViewModels"
            >
        <Window.DataContext>
            <local:AddItemsViewModel />
        </Window.DataContext>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="79*" />
                <ColumnDefinition Width="199*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="202*" />
            </Grid.RowDefinitions>
            <Label Content="Name" Height="28" HorizontalAlignment="Left" Margin="7,4,0,0" Name="label1" VerticalAlignment="Top" />
            <Label Content="Description" Height="28" HorizontalAlignment="Left" Margin="7,0,0,0" Name="label2" VerticalAlignment="Top" Grid.Row="1" />
            <Label Content="Date To Act" Height="28" HorizontalAlignment="Left" Margin="7,0,0,138" Name="label3" VerticalAlignment="Bottom" Grid.Row="2" />
            <TextBox Grid.Column="1" Text="{Binding Path=ActiveItem.Name, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="6,9,0,0" VerticalAlignment="Top" Width="181" />
            <TextBox Height="56" Text="{Binding Path=ActiveItem.Description, Mode=TwoWay}" HorizontalAlignment="Left" Margin="6,5,0,0" VerticalAlignment="Top" Width="180" Grid.Column="1" Grid.Row="1" TextWrapping="Wrap" />
            <Calendar Grid.Column="1" SelectedDate="{Binding Path=ActiveItem.DateToAct, Mode=TwoWay}" Grid.Row="2" Height="170" HorizontalAlignment="Left" Margin="7,0,0,0" VerticalAlignment="Top" Width="180" Grid.RowSpan="2" />
            <Button Content="Save" Command="{Binding SaveItem}" Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="116,10,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
        </Grid>
    </Window>

    AddItemsViewModel
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ToDoListTest.Services;
    using Domain;
    using ToDoListTest.Infrastructure;
    using System.Windows.Input;
    
    namespace ToDoListTest.ViewModels {
        public class AddItemsViewModel : ObservableObject {
    
            #region Declarations
            readonly IDialogService _dialog;
            #endregion
    
            #region Constructors
            public AddItemsViewModel() {
                this.ActiveItem = new Item();
            }
    
            public AddItemsViewModel(IDialogService dialog, Item activeItem) {
                this._dialog = dialog;
                ActiveItem = activeItem;
            }
            #endregion
    
            #region Commands
            public ICommand SaveItem {
                get { return new RelayCommand(SaveItemExecute); }
            }
            #endregion
    
            #region Properties
            Item _activeItem;
            public Item ActiveItem {
                get { return _activeItem; }
                set {
                    _activeItem = value;
                    RaisePropertyChanged("ActiveItem");
                }
            }
            #endregion
    
            #region Methods
            void SaveItemExecute() {
                try {
                    using (var toDoListDB = new ToDoDBEntities()) {
                        var i = new Item {
                            DateCreated = DateTime.Now,
                            DateToAct = this.ActiveItem.DateToAct,
                            Description = this.ActiveItem.Description,
                            ID = Guid.NewGuid(),
                            Name = this.ActiveItem.Name
                        };
                        toDoListDB.Items.AddObject(i);
                        toDoListDB.SaveChanges();
                        var addItems = new AddItems();
                        addItems.Close();
                    }
                } catch (Exception ex) {
    
                    this._dialog.ShowException(ex.Message);
                }
            }
            #endregion
    
        }
    }

    MainWindowViewModel
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Input;
    using ToDoListTest.Infrastructure;
    using Domain;
    using System.Collections.ObjectModel;
    using ToDoListTest.Services;
    using Domain.Collections;
    using System.Windows.Data;
    
    namespace ToDoListTest.ViewModels {
        public class MainWindowViewModel : ObservableObject {
    
            #region Declarations
            readonly IDialogService _dialog;
            #endregion
    
            #region Properties
            //ObservableCollection<Item> _itemResults;
            //public ObservableCollection<Item> ItemResults {
            //    get { return _itemResults; }
            //    set {
            //        _itemResults = value;
            //        RaisePropertyChanged("ItemResults");
            //    }
            //}
    
            public List<Item> ItemResults { get; set; }
    
            Item _activeItem;
            public Item ActiveItem {
                get { return _activeItem; }
                set {
                    _activeItem = value;
                    RaisePropertyChanged("ActiveItem");
                }
            }
            #endregion
    
            #region Constructors
    
            public MainWindowViewModel() : this(new ModalDialogService()) { }
    
            public MainWindowViewModel(IDialogService dialog) {
                this._dialog = dialog;
                LoadItemResults();
            }
            #endregion
    
            #region Commands
            public ICommand AddNewItem {
                get { return new RelayCommand(AddNewItemExecute); }
            }
            #endregion
    
            #region Methods
            void AddNewItemExecute() {
                if (this.ActiveItem == null) {
                    this.ActiveItem = new Item();
                }
    
                AddItemsViewModel addItemsViewModel = new AddItemsViewModel(this._dialog, this.ActiveItem);
                var addItems = new AddItems();
                addItems.Show();
            }
    
            void LoadItemResults() {
                ItemsCollection itemsCollection;
                try {
                    
                    using (var toDoListDB = new ToDoDBEntities()) {
                        //itemsCollection = new ItemsCollection(toDoListDB.Items.ToList());
                        //var itemCVS = new CollectionViewSource();
                        //var itemSource = (CollectionViewSource)this.Resources("itemSource");
                        //itemCVS.Source = toDoListDB.Items.ToList();
                        this.ItemResults = toDoListDB.Items.ToList();   
                    }
                    //ItemRepository itemRepos = new ItemRepository(new EFRepository<Item>(), new EFUnitOfWork());
                    //this.ItemResults = itemRepos.All();
                } catch (Exception ex) {
                    this._dialog.ShowException(ex.Message);
                }
            }
            #endregion
        }
    }


    Το addNew window ανοίγει απο το Command AddNewItem που βρίσκεται στο MainWindowViewModel στην γραμμή 53

    αν δεν το θες, www.antallakseto.gr
  •  30-01-2011, 18:36 62801 σε απάντηση της 62798

    Απ: Interact to mainWindow ListView

    Το IDialogService εσύ το έχεις γράψει ή είναι από κάποιο framework? Τυπικά θα πρέπει να έχει κάποιο callback ώστε να κάνεις hook το function που θες να κληθεί μόλις κλείσει το dialog.

    Πάντως γενικά το implementation δεν μου αρέσει γιατί έχει ένα πρόβλημα: Το MainWindowViewModel γνωρίζει για την ύπαρξη του AddItems view. Τυπικά, το ViewModel δεν πρέπει να ξέρει ούτε καν για το View που το χρησιμοποιεί, πόσο μάλλον για ένα άλλο τρίτο View. Υπάρχει δηλαδή ένα dependency που δεν θα έπρεπε να υπάρχει το οποίο οδηγεί σε δυσκολία στο testing, αφαιρεί μελλοντική ευελιξία για αναδιάρθρωση των Views/ViewModels, ακόμη και σε memory leaks.

    Καλύτερη υλοποίηση είναι ένας μηχανισμός messaging. Η λογική του messaging μηχανισμού είναι η εξής: Κάποιοι μεταδίδουν μηνύματα και κάποιοι αποφασίζουν να ακούν για τα μηνύματα που τους ενδιαφέρουν. Το Main ViewModel λοιπόν, μεταδίδει ένα μήνυμα ότι ο χρήστης ζήτησε να ανοίξει το dialog μαζί με κάποιες παραμέτρους για το τι χρειάζεται αυτό το dialog. Εκεί τελειώνει η δουλειά του. Αυτό το μήνυμα το παίρνει οποιοσδήποτε έχει δηλώσει ενδιαφέρον (πχ o Locator που λέγαμε προηγουμένως) και ανοίγει το dialog. Το dialog με τη σειρά του στο τέλος μεταδίδει ένα μήνυμα που λέει ότι έχει τελειώσει και δίνει ως παράμετρους τις αλλαγές. Ο Locator ξαναλμβάνει το μήνυμα και σηκώνει το Main ViewModel που χειρίζεται τις αλλαγές. Με αυτόν τον τρόπο τα δύο ViewModels είναι ανεξάρτητα και καθώς τα μηνύματα αυτά που λέμε παίζουν με weak references δεν υπάρχει κίνδυνος για memory leaks.

    Όλα αυτά θα τα βρεις υλοποιημένα στο MVVM Light ωστόσο μιας και είμαστε στα πρώτα βήματα μην χρησιμοποιήσεις απλά το framework αλλά δες του source για να καταλάβεις πώς δουλεύει.

    Έχεις πέσει σε ένα από τα κλασικά προβλήματα που συναντάς όταν παίζεις με MVVM. Αν θεωρείς ότι είναι πολλή φασαρία για τις αλλαγές που σου προτείνω ή ότι δεν θα κάνεις ποτέ testing οπότε δεν είναι μεγάλο κακό το να σηκώνεις View μέσα από το ViewModel, τότε μπορείς να βάλεις το child view να κάνει raise ένα event στο οποίο θα απαντά το parent view ωσόσο κράτησε σρο μυαλό σου ότι αυτή η τεχνική δεν ενδείκνυται.

     


    Vir prudens non contra ventum mingit
  •  30-01-2011, 19:02 62804 σε απάντηση της 62801

    Απ: Interact to mainWindow ListView

    To IDialogSerice και πολλά άλλα που έχω χρησιμοποιήσει στο app τα έχω πάρει απο ένα project (http://karlshifflett.wordpress.com/2010/11/07/in-the-box-ndash-mvvm-training/).
    Όχι δεν θεωρώ οτι είναι πολύ φασαρία αυτά που μου είπες. Εϊναι απλα ένας σωστός τρόπος και απλά πρέπει να τον μάθω και να τον συνηθίσω.

    Οπότε σε γενικές γραμμές μου προτείνεις να χρησιμοποιήσω το MVVM Light.
    Θα το κατεβάσω, θα το δοκιμάσω και ελπίζω να μου διαλευκάνει λίγο το τοπίο.

    Σε ευχαριστώ πολύ για την βοήθειά σου.


    αν δεν το θες, www.antallakseto.gr
  •  30-01-2011, 19:15 62805 σε απάντηση της 62804

    Απ: Interact to mainWindow ListView

    Μην πηδάς έτσι εύκολα από framework σε framework Big Smile Παίδεψέ το λίγο το πράγμα! Στείλε μια ερώτηση στον Karl, δες λίγο αν το IDialogService παρέχει callback functionality.

    To In the box MVVM training είναι μια χαρά για να μάθεις το MVVM και είναι πολύ σημαντικό να το μάθεις γιατί έτσι θα σου έρθουν ιδέες μελλοντικά στα διάφορα προβλήματα που θα συναντήσεις.

    Το MVVM Light είναι ένα έτοιμο πράγμα, ωστόσο μπορείς να κλέψεις από αυτό το messaging functionality. To Locator pattern μπορεί να υλοποιηθεί ανεξάρτητα και δεν χρειάζεται υποχρεωτικά το MVVM Light.

     


    Vir prudens non contra ventum mingit
  •  30-01-2011, 19:33 62807 σε απάντηση της 62805

    Απ: Interact to mainWindow ListView

    Σίγουρα θα δοκίμαζα να τελειώσω αυτό που έχω ξεκινήσει με τον υπάρχων framework πριν έπαιρνα την μεγάλη απόφαση της αλλαγής :)

    Έχω ήδη στείλει μήνυμα στον Karl και περιμένω Big Smile


    αν δεν το θες, www.antallakseto.gr
  •  30-01-2011, 20:54 62811 σε απάντηση της 62807

    Απ: Interact to mainWindow ListView

    Καμία σχέση με τα winforms τελικά Big Smile
    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  30-01-2011, 21:20 62814 σε απάντηση της 62811

    Απ: Interact to mainWindow ListView

    Και όμως Δήμο, αν υλοποιήσεις winforms με το Model View Presenter pattern, πολλά από αυτά βρίσκουν εφαρμογή κι εκεί...

     


    Vir prudens non contra ventum mingit
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems