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

 

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

Messages should be closed, somehow, manually?

Îåêßíçóå áðü ôï ìÝëïò StrouMfios. Τελευταία δημοσίευση από το μέλος StrouMfios στις 18-02-2011, 15:15. Υπάρχουν 6 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  17-02-2011, 19:51 63365

    Messages should be closed, somehow, manually?

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

    όπως μου είχε προτείνει ο KelMan(τον ευχαριστώ πολύ) χρησιμοποιώ το mediator Pattern για επικοινωνία μεταξύ viewModel και view.

    λοιπόν,
    στο mainWindow έχω ενα menu όπου σε κάθε item του έχω ορίσει ενα command.
    Όταν κάνω click σε ένα item στέλνω μήνυμα το οποίο το έχω κάνει register στο mainWindow.xaml.cs
    //MainWindow.xaml
    <awc:ImageButton IsToolStyle="True"  Orientation="Vertical" ImageSource="" Command="{Binding ShowPricesWindowCommand}">Prices</awc:ImageButton>
    
    
     //MainWIndow ViewModel
     public ICommand ShowPricesWindowCommand {
            get { return new RelayCommand(ShowPricesWindowExecute); }
        }
    void ShowPricesWindowExecute() {
            Messenger.Default.Send(new NotificationMessage<Hotel>(this, SelectedHotel, "ShowPricesWindow"),
                                   "ShowPricesWindow");
        }
    
    
    //MainWindow.xaml.cs
    Messenger.Default.Register<NotificationMessage<Hotel>>(this, "ShowPricesWindow", HotelPriceMessageReceived);
    
    private void HotelPriceMessageReceived(NotificationMessage<Hotel> selectedHotel) {
            var roomPrices = new RoomPrices();//This view has the RoomPriceViewModel as dataContext
            roomPrices.Show();
            //via messaging I am sending the selectedHotel object
            Messenger.Default.Send(new NotificationMessage<Hotel>(this, selectedHotel.Content, "ShowPricesWindow"),
                                   "ShowPricesWindow2");
        }

    μου ανοίγει το ζητούμενο παράθυρο και μέσα απο το viewModel του(RoomPricesViewModel), κάνω κάποιον έλεγχο και κλείνω το view που είχε ανοίξει και ανοίγω ένα άλλο.

    public RoomPricesViewModel(IDialogService dialogService) {
            this._dialog = dialogService;
            Messenger.Default.Register<NotificationMessage<Hotel>>(this, "ShowPricesWindow2", NotificationMessageReceived);
        }
    
        private void NotificationMessageReceived(NotificationMessage<Hotel> selectedHotel) {
            this.SelectedHotel = selectedHotel.Content;
            LoadRooms();
        }
    
    void LoadRooms() {
            if (rooms.Count == 0) {
                dialogResponse = _dialog.ShowMessage("Display a message;", "", DialogButton.YesNo, DialogImage.Warning);
                switch (dialogResponse) {
                    case DialogResponse.Yes:
                        //close the RoomPrices window and open the RoomTypesWindow
                        Messenger.Default.Send(new NotificationMessage<Hotel>(this, this.SelectedHotel, "CloseWindowAndOpenRoomTypes"), "CloseWindowAndOpenRoomTypes");
                        return;
                        break;
                    case DialogResponse.No:
                        break;
                }
            }
        }
    public RoomPrices() {
                InitializeComponent();
                Messenger.Default.Register<NotificationMessage<Hotel>>(this, "CloseWindowAndOpenRoomTypes", CloseWindowAndOpenRoomTypes);
            }
    
     private void CloseWindowAndOpenRoomTypes(NotificationMessage<Hotel> selectedHotel) {
                if (selectedHotel.Sender == this.DataContext) {
                    this.Close();
                    Messenger.Default.Send(new NotificationMessage<Hotel>(this, selectedHotel.Content, "ShowRoomsWindow"),
                                       "ShowRoomsWindow");
                }
            }

    Αυτή η διαδικάσία λειτουργεί "σωστά" για μία φορά μόνο.

    Αν κλείσω και το δεύτερο παράθυρο που έχει ανοίξει και ξαναπατήσω το item στο menu, τότε η όλη διαδικασία θα επαναληφθεί δύο φορές.

    Το ίδιο συμβαίνει για όσες φορές και αν πατήσω το item.

    Πρέπει τα messages να τα κλείνω με κάποιον τρόπο?

    Ευχαριστώ


    αν δεν το θες, www.antallakseto.gr
    Δημοσίευση στην κατηγορία: ,
  •  18-02-2011, 11:21 63376 σε απάντηση της 63365

    Απ: Messages should be closed, somehow, manually?

    Χμμμ... Για κάνε έναν έλεγχο πόσα views έχεις αφού ανοίξεις δυο-τρεις φορές το view. Έχω μια υποψία ότι δεν γίνονται dispose τα views και γι αυτό παραμένουν τα registrations των μηνυμάτων.

    Τα messages από μόνα τους είναι objects με weak references, το πολύ να χρειαστεί να κάνεις unsubscribe ωστόσο αν συμβαίνει αυτό που σου είπα προηγουμένως τότε δεν λύνεις το πρόβλημά σου καθώς συνεπάγεται ότι έχεις memory leaks.

     


    Vir prudens non contra ventum mingit
  •  18-02-2011, 11:35 63377 σε απάντηση της 63376

    Απ: Messages should be closed, somehow, manually?

    Τα messages τα κάνω register στον constructor, οπότε όσες φορές άνοιγα το παράθυρο τόσες φορές γινόταν register το message.
    Έκανα unregister το message και δείχνει να δουλεύει, αλλα το θέμα είναι οτι δεν ξέρω αν γίνονται, όπως είπες, dispose τα views.
    Πως μπορώ να δω αν τα views δεν έχουν γίνει dispose?



    αν δεν το θες, www.antallakseto.gr
  •  18-02-2011, 12:21 63382 σε απάντηση της 63377

    Απ: Messages should be closed, somehow, manually?

    Αυτό τώρα εξαρτάται από τον κώδικά σου και το πώς ανοίγεις/κλείνεις τα views, δεν υπάρχει συγκεκριμένος τρόπος. Δες εκεί που κλείνει το παράθυρο τι ακριβώς κάνεις.

     


    Vir prudens non contra ventum mingit
  •  18-02-2011, 12:27 63383 σε απάντηση της 63382

    Απ: Messages should be closed, somehow, manually?

    Δεν κάνω κάτι συγκεκριμένο όταν κλείνω το παράθυρο. Απλά το κλείνω απο το (Χ).
    Μάλλον κάτι θα έπρεπε να κάνω ε?  Big Smile

    αν δεν το θες, www.antallakseto.gr
  •  18-02-2011, 12:31 63384 σε απάντηση της 63383

    Απ: Messages should be closed, somehow, manually?

    Προφανώς μένει κάποιο reference προς το παράθυρο...
    Vir prudens non contra ventum mingit
  •  18-02-2011, 15:15 63397 σε απάντηση της 63384

    Απ: Messages should be closed, somehow, manually?

    Δεν μπορώ να καταλάβω που είναι το λάθος.
    Τελικά το unregister του message δεν είναι λύση.

    Το ίδιο πρόβλημα παρουσιάστηκε και σε άλλο σημείο της εφαρμογής. Οπότε κάτι κάνω λάθος και δεν ξέρω τι είναι αυτό.
    Θα εκτιμούσα οποιαδήποτε βοήθεια. Το ψάχνω πολύ ώρα τώρα και δεν έχω καταφέρει τίποτα.


    Η διαδικασία είναι η εξής: 
    1. ανοίγει ένα παράθυρο και ο χρήστης κάνει εισαγωγή σε ένα textBox.
    2. Πατάει save και εκτελείτε το AddNewHotelCommand --> κατόπιν η AddNewHotelExecute()
    3. Γίνεται persist στην βάση, και γίνεται αποστολή ενός NotificationMessage για να κλείσει το view, το οποίο έχει γίνει register στο codeBehind του view.
    4. Εκτελείται η μέθοδος NotificationMessageReceived   και κλείνει το view  (εδώ είναι το πρόβλημα) 
      1. Το κακό είναι οτι όσες φορές και αν πατήσω το button για να ανοίξει το view, τόσες φορές θα μπεί σε αυτή την μέθοδο.  Εννοώ οτι πατάω το button, ανοίγει το view, το κλείνω(Μπήκε μία φορά). Κάνω την ίδια διαδικασία (μπαίνει δύο φορές) κ.ο.κ.

    Αυτός είναι ο κώδικάς μου:

    Hotel_Add_Select.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
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ViewModels="clr-namespace:HMT.ViewModels"    
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            mc:Ignorable="d" x:Class="HMT.WIndows.Hotel_Add_Select"    
            Height="400" Width="600">
    
        <Window.DataContext>
            <ViewModels:AddHotelsViewModel />
        </Window.DataContext>
        
        <Grid>
            <Grid Height="93" VerticalAlignment="Top">
                <Grid.RowDefinitions>
                    <RowDefinition Height="32*" />
                    <RowDefinition Height="61*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="147*" />
                    <ColumnDefinition Width="318*" />
                </Grid.ColumnDefinitions>
                <Label Content="Όνομα ξενοδοχείου" Grid.ColumnSpan="2" Grid.RowSpan="2" VerticalAlignment="Top" HorizontalAlignment="Left"/>
                <TextBox Grid.Column="1" Text="{Binding ActiveHotel.Name, Mode=TwoWay, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, ValidatesOnExceptions=True}" Style="{DynamicResource mainTextBox}" VerticalAlignment="Top" HorizontalAlignment="Left"/>
                <Button Command="{Binding AddNewHotelCommand}" Width="150" Height="30" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Αποθήκευση" Grid.Row="1" Grid.Column="1" Style="{DynamicResource mainButton}" d:IsLocked="True"/>
            </Grid>
        </Grid>
    </Window>

    AddHotelsViewModel
    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
     
    public class AddHotelsViewModel : ObservableObject {
            #region Declarations
            readonly IDialogService _dialog;
            #endregion
    
            #region Properties
    
            private Hotel _activeHotel { get; set; }
            public Hotel ActiveHotel {
                get { return _activeHotel; }
                set {
                    _activeHotel = value;
                    RaisePropertyChanged("ActiveHotel");
                }
            }
    
            private Hotel _selectedHotel { get; set; }
            public Hotel SelectedHotel {
                get { return _selectedHotel; }
                set {
                    _selectedHotel = value;
                    RaisePropertyChanged("SelectedHotel");
    
                    //Sends message to mainWindowViewModel
                    Messenger.Default.Send(new NotificationMessage<Hotel>(this, SelectedHotel, "SelectedHotel"));
                }
            }
    
            private bool _isValid;
            public bool IsValid {
                get { return _isValid; }
                set {
                    _isValid = value;
                    RaisePropertyChanged("IsValid");
                }
            }
            #endregion
    
            #region Constructors
    
            public AddHotelsViewModel()
                : this(new ModalDialogService()) {
            }
    
            public AddHotelsViewModel(IDialogService dialogService) {
                this._dialog = dialogService;
                this.ActiveHotel = new Hotel();
            }
            #endregion
    
            #region Commands
    
            public ICommand AddNewHotelCommand {
                get { return new RelayCommand(AddNewHotelExecute, CanAddNewHotel); }
            }
            #endregion
    
            #region Methods
    
            void AddNewHotelExecute() {
                try {
                    var unitOfWork = new EFUnitOfWork();
                    var hotelRepos = new HotelRepository(new EFRepository<Hotel>(), unitOfWork);
                    hotelRepos.Add(this.ActiveHotel);
                    unitOfWork.Save();
                    _dialog.ShowMessage("Το ξενοδοχείο καταχωρήθηκε με επιτυχία", "Μήνυμα", DialogButton.OK, DialogImage.None);
                    this.SelectedHotel = this.ActiveHotel;
                    Messenger.Default.Send(new NotificationMessage(this, "CloseAddHotelWIndow"), "CloseAddHotelWIndow");
                } catch (Exception ex) {
                    _dialog.ShowException(ex.Message, DialogImage.Error);
                }
            }
    
            public bool CanAddNewHotel() {
                return IsValid;
            }
            #endregion
        }

    Hotel_Add_Select.xaml.cs
    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
     
    public partial class Hotel_Add_Select : Window {
    
            private readonly HashSet<ValidationError> errors = new HashSet<ValidationError>();
            private Lazy<AddHotelsViewModel> viewModel;
    
            public Hotel_Add_Select() {
                InitializeComponent();
                InitializeValidaton();
                this.PreviewKeyDown += new KeyEventHandler(CloseOnEscape);
                Messenger.Default.Register<NotificationMessage>(this, "CloseAddHotelWIndow", NotificationMessageReceived);
            }
    
            protected override void OnClosing(CancelEventArgs e) {
                if (viewModel.Value.SelectedHotel == null) {
                    e.Cancel = true;
                    var messageBoxResult = MessageBox.Show("Δεν έχετε εισάγει ξενοδοχείο.Κλείσιμο του παραθύρου χωρίς εισαγωγή ξενοδοχείου;", "Προσοχή", MessageBoxButton.YesNo,
                                    MessageBoxImage.Error);
                    switch (messageBoxResult) {
                        case MessageBoxResult.Yes:
                            e.Cancel = false;
                            break;
                        case MessageBoxResult.No:
                            e.Cancel = true;
                            break;
                    }
                    return;
                }
            }
    
            //*************************** Εδώ μπαίνει πολλές φορές   ******************************
            //Όσες φορές γίνει click στο button για να ανοίξει το view,  τόσες φορές θα έρθει σε αυτή την μέθοδο.
    
            private void NotificationMessageReceived(NotificationMessage msg) {
                if (!string.IsNullOrEmpty(msg.Notification)) {
                    switch (msg.Notification) {
                        case "CloseAddHotelWIndow":
                            Close();
                            break;
                    }
                }
            }
    
            private void CloseOnEscape(object sender, KeyEventArgs e) {
                if (e.Key == Key.Escape)
                    Close();
            }
    
            void InitializeValidaton() {
                viewModel = new Lazy<AddHotelsViewModel>(() => (AddHotelsViewModel)this.DataContext);
                Validation.AddErrorHandler(this, ErrorChangedHandler);
            }
    
            private void ErrorChangedHandler(object sender, ValidationErrorEventArgs e) {
                if (e.Action == ValidationErrorEventAction.Added) {
                    errors.Add(e.Error);
                    this.Unloaded += new RoutedEventHandler(Hotel_Add_Select_Unloaded);
                } else {
                    errors.Remove(e.Error);
                }
                viewModel.Value.IsValid = !errors.Any();
            }
    
            void Hotel_Add_Select_Unloaded(object sender, RoutedEventArgs e) {
                ((FrameworkElement)sender).Unloaded -= Hotel_Add_Select_Unloaded;
                errors.Clear();
                viewModel.Value.IsValid = !errors.Any();
            }
        }

    Ευχαριστώ πολύ

    αν δεν το θες, www.antallakseto.gr
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems