Καλησπέρα σε όλους,
προσπαθώ να φτιάξω μια μικρή εφαρμογή σε wpf με το Pattern mvvm.
Στο data layer για βάση δεδομένων χρησιμοποιώ .sdf file και Entity Framework.
H εφαρμογή έχει 3 views και ενα ViewModel
Στο dataContext του mainWindow κάνω bind το ViewModel και τα άλλα δυο userControls παίζουν με το ίδιο ViewModel.
Σε ένα UserControl έχω ένα property με όνομα isValid το οποίο το ενημερώνω απο το mainWindow.xaml.cs.
Το πρόβλημα είναι οτι ενώ το property ενημερώνετε σωστά, για κάποιο λόγο γίνεται συνέχεια initialize με αποτέλεσμα να φέρνει πάντα την default τιμή (false δηλαδή).
Αυτό συμβαίνει στο AddItemsView.xaml
PLEASE!!!!!!!!! HELP!!!!!!
Ευχαριστώ εκ των προτέρων για την οποιαδήποτε βοήθεια
Παρακάτω είναι ο κώδικας
MainWindow.xaml
<Window x:Class="ToDoListTest.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ToDoListTest.Views"
xmlns:ViewModels="clr-namespace:ToDoListTest.ViewModels"
xmlns:tb="clr-namespace:Hardcodet.Wpf.TaskbarNotification;assembly=Hardcodet.Wpf.TaskbarNotification"
Title="MainWindow" MinHeight="380" Width="620" Height="300" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" ResizeMode="CanMinimize">
<Window.DataContext>
<ViewModels:MainWindowViewModel />
</Window.DataContext>
<DockPanel>
<tb:TaskbarIcon
x:Name="MyNotifyIcon"
IconSource="/Images/Icons/Error.ico"
ToolTipText="ToDoList" />
<StackPanel DockPanel.Dock="Top">
<DockPanel>
<local:ViewItemsList DockPanel.Dock="Left"></local:ViewItemsList>
<local:AddItemsView DockPanel.Dock="Right" BorderBrush="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</DockPanel>
</StackPanel>
<Grid Background="#FFD8D8D8">
<local:StatusBar DockPanel.Dock="Bottom"></local:StatusBar>
</Grid>
</DockPanel>
</Window>
mainWIndow.xaml.csusing System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;
using Domain;
using Samples;
using ToDoListTest.ViewModels;
namespace ToDoListTest.Views {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
private readonly HashSet<ValidationError> errors = new HashSet<ValidationError>();
private Lazy<MainWindowViewModel> viewModel;
public MainWindow() {
InitializeComponent();
InitializeValidaton();
SetInterval();
}
void InitializeValidaton() {
viewModel = new Lazy<MainWindowViewModel>();
Validation.AddErrorHandler(this, ErrorChangedHandler);
}
private void ErrorChangedHandler(object sender, ValidationErrorEventArgs e) {
if (e.Action == ValidationErrorEventAction.Added) {
errors.Add(e.Error);
} else {
errors.Remove(e.Error);
}
viewModel.Value.IsValid = !errors.Any();
}
void SetInterval() {
var dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 1, 0);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e) {
try {
var unitOfWork = new EFUnitOfWork();
var itemRepository = new ItemRepository(new EFRepository<Item>(), unitOfWork);
var item = itemRepository.GetActive();
if (item != null) {
//Update the status
item.Status = true;
itemRepository.Save();
unitOfWork.Save();
var balloon = new FancyBalloon();
balloon.BalloonText = item.Name;
balloon.BalloonDescription = item.Description;
//show balloon and close it after 4 seconds
MyNotifyIcon.ShowCustomBalloon(balloon, PopupAnimation.Slide, 4000);
}
} catch (Exception ex) {
//swallow
}
}
}
}
AddItemsView.xaml<UserControl
x:Class="ToDoListTest.Views.AddItemsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="310" d:DesignWidth="200">
<Grid Height="312">
<Grid.RowDefinitions>
<RowDefinition Height="55" />
<RowDefinition Height="89" />
<RowDefinition Height="62" />
<RowDefinition Height="56" />
<RowDefinition Height="37*" />
</Grid.RowDefinitions>
<Label Content="Name" Height="28" HorizontalAlignment="Left" Margin="12,0,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="Description" Height="28" HorizontalAlignment="Left" Margin="12,51,0,0" Name="label2" VerticalAlignment="Top" Grid.RowSpan="2" />
<TextBox Text="{Binding Path=ActiveItem.Name, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true,ValidatesOnExceptions=True, NotifyOnValidationError=True}" Height="23" HorizontalAlignment="Left" Margin="12,22,0,0" VerticalAlignment="Top" Width="176" />
<TextBox Height="56" Text="{Binding Path=ActiveItem.Description, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true}" HorizontalAlignment="Left" Margin="12,22,0,0" VerticalAlignment="Top" Width="176" TextWrapping="Wrap" Grid.Row="1" />
<Button Content="Save" Command="{Binding Path=SaveItem}" CommandParameter="{Binding}" Height="25" HorizontalAlignment="Left" Margin="113,14,0,0" Name="button1" VerticalAlignment="Top" Width="75" Grid.Row="4" />
<Label Content="Date to act" Height="28" HorizontalAlignment="Left" Margin="12,0,0,0" Name="label4" VerticalAlignment="Top" Grid.Row="2" />
<DatePicker SelectedDate="{Binding Path=ActiveItem.DateToAct, Mode=TwoWay}" Height="25" HorizontalAlignment="Left" Margin="12,0,0,5" Name="datePicker1" VerticalAlignment="Bottom" Width="176" Grid.Row="2" />
<Label Content="Time to act" Height="28" HorizontalAlignment="Left" Margin="14,0,0,0" Name="label3" VerticalAlignment="Top" Grid.Row="3" />
<ComboBox Grid.Row="3" SelectedItem="{Binding Path=ActiveItem.Hour}" ItemsSource="{Binding Path=Hours}" DisplayMemberPath="" Height="23" HorizontalAlignment="Left" Margin="14,23,0,0" Name="hourDDL" VerticalAlignment="Top" Width="40" />
<ComboBox Grid.Row="3" SelectedItem="{Binding Path=ActiveItem.Minute}" ItemsSource="{Binding Path=Minutes}" Height="23" HorizontalAlignment="Right" Margin="0,23,100,0" Name="minuteDDL" VerticalAlignment="Top" Width="40" />
</Grid>
</UserControl>
AddItemsView.xaml.csusing System;
using System.Windows.Controls;
using ToDoListTest.ViewModels;
namespace ToDoListTest.Views {
/// <summary>
/// Interaction logic for AddItemsView.xaml
/// </summary>
public partial class AddItemsView : UserControl {
public AddItemsView() {
InitializeComponent();
}
}
}
MainWindowViewModel.csΜε κόκκινο είναι η μέθοδος που γίνεται συνέχεια initialize
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Threading;
using Domain.Infrastructure;
using Samples;
using Domain;
using System.Collections.ObjectModel;
using ToDoListTest.Services;
using System.Collections.Generic;
using System.Waf.Applications;
namespace ToDoListTest.ViewModels {
public class MainWindowViewModel : ObservableObject {
#region Declarations
readonly IDialogService _dialog;
#endregion
#region Properties
......
private bool _isValid;
public bool IsValid {
get { return _isValid; }
set {
_isValid = value;
RaisePropertyChanged("IsValid");
}
}
#endregion
#region Constructors
public MainWindowViewModel() : this(new ModalDialogService()) { }
public MainWindowViewModel(IDialogService dialog) {
this._dialog = dialog;
ItemResults = new ObservableCollection<Item>();
ShowNewItemForm = "Hidden";
Status = "Ready";
LoadItemResults();
PrepareHoursAndMinutes();
}
#endregion
#region Commands
public ICommand AddNewItem {
get { return new RelayCommand(AddNewItemExecute); }
}
public ICommand SaveItem {
get { return new RelayCommand(SaveItemExecute,CanSaveItem); }
}
.........
#endregion
#region Methods
public void SaveItemExecute() {
if (ActiveItem == null) {
_dialog.ShowMessage("Please select an item from the list to update it, or click the {New} button to create a new item.", "Oops!!", DialogButton.OK, DialogImage.Error);
return;
}
if (ActiveItem.EntityKey != null) {
UpdateItem();
return;
}
try {
var i = new Item {
DateCreated = DateTime.Now,
DateToAct = this.ActiveItem.DateToAct,
Description = this.ActiveItem.Description,
Name = this.ActiveItem.Name,
TimeToAct = ActiveItem.TimeToAct,
Status = false
};
var unitOfWork = new EFUnitOfWork();
var itemRepository = new ItemRepository(new EFRepository<Item>(), unitOfWork);
itemRepository.Add(i);
unitOfWork.Save();
ItemResults.Add(i);
ActiveItem = new Item();
Status = "Saved!";
} catch (Exception ex) {
this._dialog.ShowException(ex.Message);
}
}
public bool CanSaveItem() {
return IsValid;
}
..............
#endregion
}
}
Entityusing System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Waf.Foundation;
namespace Domain {
internal interface IItem {
[Required(ErrorMessage = "Please enter Title")]
[StringLength(100, ErrorMessage = "The maximum length is 100")]
string Name { get; set; }
}
[MetadataType(typeof(IItem))]
public partial class Item : IItem, IDataErrorInfo, IFormattable {
[NonSerialized]
private readonly DataErrorInfoSupport dataErrorInfoSupport;
public Item() {
ID = Guid.NewGuid();
dataErrorInfoSupport = new DataErrorInfoSupport(this);
}
string IDataErrorInfo.this[string memberName] { get { return dataErrorInfoSupport[memberName]; } }
public string Error {
get {
return dataErrorInfoSupport.Error;
}
}
}
}
Έχω κάνει και αυτο το
post, αλλα είπα να κάνω καινούριο για να είναι πιο ξεκάθαρο το πρόβλημα που αντιμετωπίζω.
αν δεν το θες,
www.antallakseto.gr