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

-
Μέλος από τις 05-03-2009
-
-
Δημοσιεύσεις 105
-
-
|
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
|
-
KelMan
-
-
-
Μέλος από τις 03-11-2004
-
Planet Earth
-
Δημοσιεύσεις 2.851
-
-
|
Απ: 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
|
-
StrouMfios
-
-

-
Μέλος από τις 05-03-2009
-
-
Δημοσιεύσεις 105
-
-
|
Απ: 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
|
-
KelMan
-
-
-
Μέλος από τις 03-11-2004
-
Planet Earth
-
Δημοσιεύσεις 2.851
-
-
|
Απ: Messages should be closed, somehow, manually?
Αυτό τώρα εξαρτάται από τον κώδικά σου και το πώς ανοίγεις/κλείνεις τα views, δεν υπάρχει συγκεκριμένος τρόπος. Δες εκεί που κλείνει το παράθυρο τι ακριβώς κάνεις.
Vir prudens non contra ventum mingit
|
|
-
18-02-2011, 12:27
|
-
StrouMfios
-
-

-
Μέλος από τις 05-03-2009
-
-
Δημοσιεύσεις 105
-
-
|
Απ: Messages should be closed, somehow, manually?
Δεν κάνω κάτι συγκεκριμένο όταν κλείνω το παράθυρο. Απλά το κλείνω απο το (Χ). Μάλλον κάτι θα έπρεπε να κάνω ε? 
αν δεν το θες, www.antallakseto.gr
|
|
-
18-02-2011, 12:31
|
-
KelMan
-
-
-
Μέλος από τις 03-11-2004
-
Planet Earth
-
Δημοσιεύσεις 2.851
-
-
|
Απ: Messages should be closed, somehow, manually?
Προφανώς μένει κάποιο reference προς το παράθυρο...
Vir prudens non contra ventum mingit
|
|
-
18-02-2011, 15:15
|
-
StrouMfios
-
-

-
Μέλος από τις 05-03-2009
-
-
Δημοσιεύσεις 105
-
-
|
Απ: Messages should be closed, somehow, manually?
Δεν μπορώ να καταλάβω που είναι το λάθος. Τελικά το unregister του message δεν είναι λύση.
Το ίδιο πρόβλημα παρουσιάστηκε και σε άλλο σημείο της εφαρμογής. Οπότε κάτι κάνω λάθος και δεν ξέρω τι είναι αυτό. Θα εκτιμούσα οποιαδήποτε βοήθεια. Το ψάχνω πολύ ώρα τώρα και δεν έχω καταφέρει τίποτα.
Η διαδικασία είναι η εξής: - ανοίγει ένα παράθυρο και ο χρήστης κάνει εισαγωγή σε ένα textBox.
- Πατάει save και εκτελείτε το AddNewHotelCommand --> κατόπιν η AddNewHotelExecute()
- Γίνεται persist στην βάση, και γίνεται αποστολή ενός NotificationMessage για να κλείσει το view, το οποίο έχει γίνει register στο codeBehind του view.
- Εκτελείται η μέθοδος NotificationMessageReceived και κλείνει το view (εδώ είναι το πρόβλημα)
- Το κακό είναι οτι όσες φορές και αν πατήσω το 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
|
|
|
|
|