Wpf og MVVM
Hej,Jeg er i gang med at gå igennem en youtube serie med VPF og MVVM og her har jeg så opdaget en fejl, jeg ikke kan hitte ud af.
Jeg åbner en side, hvor der er 3 labels 3 textboxes 4 buttons. Id, Name og Age skal det stå for. og så en grid, hvor der bliver vist en Employee (= mit eget navn).
Den ene button er Add - altså tilføj. Når jeg tilføjer første gang, så går det godt. Nu er der 2 employes i gridviewet Anja og så Sigurd på 44.
Så kommer fejlen, når jeg så tilføjer en eller flere employees - så ændrer den Sigurd (og den næste indsatte employee) Lise med Lises name Id og Age. Altså den første tuple (kan ikke huske hvad sådan en række hedder) bliver vist korrekt, mens de efterfølgende rækker får den sidste rækkes, jeg har sat ind, data.
Jeg mistænker, det er i EmployeeViewModel, der er et problem og her specifikt når jeg kører mellem CurrentEmployee og objEmployee men jeg er desværre ikke god nok til at finde ud af, hvad jeg skal ændre og hvor.
Hvis I ønsker at jeg zipper det hele ned, og kan så sende til jer pr. mail, ved interesse. Der er ingen statshemmeligheder.
Hvis I mangler et eller andet mere, end neden viste kode, så sig endelig til.
Jeg har adskilt hver del med ------- så det forhåbentligt er nemmere at læse.
Vh
Simsen :-)
Models.Employees
namespace MvvmDemo.Models
{
public class Employee : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private int id;
public int Id
{
get => id;
set { id = value; OnPropertyChanged("Id"); }
}
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
private int age;
public int Age
{
get { return age; }
set { age = value; OnPropertyChanged("Age"); }
}
}
}
-----------------------------------------------------------------------------------
Models.EmployeeService (her kommer et senere spørgsmål, altså hvis jeg kan få det her til at virke)
namespace MvvmDemo.Models
{
public class EmployeeService
{
private static List<Employee> ObjEmployeesList;
public EmployeeService()
{
ObjEmployeesList = new List<Employee>()
{
new Employee { Id=101, Name="Anja", Age=55 }
};
}
public List<Employee> GetAll()
{
return ObjEmployeesList;
}
public bool Add(Employee objNewEmployee)
{
//Age must be between 21 and 58
if (objNewEmployee.Age < 21 || objNewEmployee.Age > 58)
throw new ArgumentException("Invalid Age limit for Employee");
ObjEmployeesList.Add(objNewEmployee);
return true;
}
public bool Update (Employee objEmployeeToUpdate)
{
bool IsUpdated = false;
for (int index = 0; index <ObjEmployeesList.Count; index++)
{
if (ObjEmployeesList[index].Id==objEmployeeToUpdate.Id)
{
ObjEmployeesList[index].Name = objEmployeeToUpdate.Name;
ObjEmployeesList[index].Age = objEmployeeToUpdate.Age;
IsUpdated = true;
break;
}
}
return IsUpdated;
}
public bool Delete (int id)
{
bool IsDeleted = false;
for (int index = 0; index < ObjEmployeesList.Count; index++)
{
if (ObjEmployeesList[index].Id == id)
{
ObjEmployeesList.RemoveAt(index);
IsDeleted = true;
break;
}
}
return IsDeleted;
}
public Employee Search(int id)
{
return ObjEmployeesList.FirstOrDefault(e => e.Id == id);
}
}
}
----------------------------------------------------------------------------------------------
Commands.RelayCommand
namespace MvvmDemo.Commands
{
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private readonly Action DoWork;
public RelayCommand(Action work)
{
DoWork = work;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
DoWork();
}
}
}
-----------------------------------------------------------------------------
Views.EmployeeView
<UserControl x:Class="MvvmDemo.Views.EmployeeView"
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"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d">
<Grid Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<!--Row 0-->
<TextBlock Text="Employee Management" Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="2" FontSize="20" FontWeight="Bold"
HorizontalAlignment="Center" Margin="5,8" Padding="3"/>
<!--Row 1-->
<TextBlock Text="Enter Id" Grid.Row="1" Grid.Column="0" />
<TextBox x:Name="txtId" Grid.Row="1" Grid.Column="1" Margin="5,8"
Padding="3" Text="{Binding Path=CurrentEmployee.Id, Mode=TwoWay}" />
<!--Row 2-->
<TextBlock Text="Enter Name" Grid.Row="2" Grid.Column="0" />
<TextBox x:Name="txtName" Grid.Row="2" Grid.Column="1" Margin="5,8" Padding="3"
Text="{Binding Path=CurrentEmployee.Name, Mode=TwoWay}"/>
<!--Row 3-->
<TextBlock Text="Enter Age" Grid.Row="3" Grid.Column="0" />
<TextBox x:Name="txtAge" Grid.Row="3" Grid.Column="1" Margin="5,8" Padding="3"
Text="{Binding Path=CurrentEmployee.Age, Mode=TwoWay}"/>
<!--Row 4-->
<StackPanel Orientation="Horizontal" Grid.Row="4" Grid.Column="1">
<Button x:Name="btnAdd" Content="Add" Margin="5,8" Padding="3"
Command="{Binding Path=SaveCommand}"/>
<Button x:Name="btnSearch" Content="Search" Margin="5,8" Padding="3"
Command="{Binding Path=SearchCommand}"/>
<Button x:Name="btnUpdate" Content="Update" Margin="5,8" Padding="3" />
<Button x:Name="btnDelete" Content="Delete" Margin="5,8" Padding="3" />
</StackPanel>
<!--Row 5-->
<TextBlock x:Name="txtMessage" Grid.Column="1" Grid.Row="5" Margin="5,8" Padding="3"
Text="{Binding Path=Message}"/>
<!--Row 6-->
<DataGrid Name="dgEmployees" AutoGenerateColumns="False" Grid.Row="6" Grid.Column="1"
Margin="5,8" Padding="3" ItemsSource="{Binding Path=EmployeeList, Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTextColumn Header="Employee Id" Width="auto" Binding="{Binding Path=Id}" />
<DataGridTextColumn Header="Employee Name" Width="auto" Binding="{Binding Path=Name}" />
<DataGridTextColumn Header="Employee Age" Width="auto" Binding="{Binding Path=Age}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
------------------------------------------------------------
ViewModels.EmployeeViewModel
namespace MvvmDemo.ViewModels
{
public class EmployeeViewModel : INotifyPropertyChanged
{
#region INotifyPropertyChanged_Implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
readonly EmployeeService ObjEmployeeService;
public EmployeeViewModel()
{
ObjEmployeeService = new EmployeeService();
LoadData();
CurrentEmployee = new Employee();
saveCommand = new RelayCommand(Save);
searchCommand = new RelayCommand(Search);
}
#region DisplayOperation
private ObservableCollection<Employee> employeeList;
public ObservableCollection<Employee> EmployeeList
{
get { return employeeList; }
set { employeeList = value; OnPropertyChanged("EmployeeList"); }
}
private void LoadData()
{
EmployeeList = new ObservableCollection<Employee>(ObjEmployeeService.GetAll());
}
#endregion
private Employee currentEmployee;
public Employee CurrentEmployee
{
get { return currentEmployee; }
set { currentEmployee = value; OnPropertyChanged("CurrentEmployee"); }
}
private readonly RelayCommand saveCommand;
private string message;
public string Message
{
get { return message; }
set { message = value; OnPropertyChanged("Message"); }
}
#region SaveOperation
public RelayCommand SaveCommand
{
get { return saveCommand; }
}
public void Save()
{
try
{
var isSaved = ObjEmployeeService.Add(CurrentEmployee);
LoadData();
if (isSaved)
Message = "Employee saved";
else
Message = "Save operation failed";
}
catch (Exception ex)
{
Message = ex.Message;
}
}
#endregion
#region Search Operation
private readonly RelayCommand searchCommand;
public RelayCommand SearchCommand
{
get { return searchCommand; }
}
public void Search()
{
try
{
var objEmployee = ObjEmployeeService.Search(CurrentEmployee.Id);
if (objEmployee != null)
{
CurrentEmployee.Name = objEmployee.Name;
CurrentEmployee.Age = objEmployee.Age;
}
else
{
Message = "Employee Not found";
}
}
catch (Exception ex)
{
Message = ex.Message;
}
}
#endregion
}
}