Aplikasi WPF CRUD Menggunakan DataGrid, MVVM Pattern, Entity Framework, Dan C # .NET

  • Whatsapp
Aplikasi WPF CRUD Menggunakan DataGrid, MVVM Pattern, Entity Framework, Dan C # .NET

Selamat siang untuk semuanya!

Berikut adalah contoh proyek WPF CRUD (Buat, Perbarui dan Hapus) menggunakan kontrol DataGrid, ADO.NET Entity Framework 6.x, C # .NET dan pola arsitektur Model – View – Viewmodel (MVVM). Posting ini didasarkan dari tutorial ini WPF CRUD Dengan DataGrid, Entity Framework Dan C # .NET kecuali bahwa kita sekarang menggunakan kerangka MVVM. Langkah-langkah di bawah ini cukup mudah dan mudah diikuti.

I. Setup Proyek

1. Tambahkan tabel bernama Siswa di database Anda. Skrip lengkap ditemukan di posting ini WPF CRUD Dengan DataGrid, Entity Framework Dan C # .NET
2. Buat Proyek WPF dan tambahkan empat folder bernama DataAccess, Model, View dan ViewModel.
3. Struktur proyek Anda mungkin terlihat serupa dengan gambar yang disediakan di bawah ini.

Bacaan Lainnya

II. Pengkodean Kelas Model dan Repositori

1. Di dalam folder Model, tambahkan Model Data Entitas ADO.NET yang terhubung ke tabel Siswa di database Anda. Di pihak saya, saya menamainya StudentModel.
2. Untuk nama string koneksi, saya mengubahnya menjadi StudentEntities.
3. Selanjutnya adalah menambahkan StudentRecord kelas yang memiliki properti yang sesuai dengan kolom tabel dan properti ObservableCollection digunakan sebagai itemsource untuk datagrid. Kelas ini mewarisi ViewModelBase class ditambahkan di folder ViewModel yang akan disebutkan di Coding Bagian ViewModel Classes sehingga ada mekanisme dalam menangani perubahan properti dan notifikasi dari kontrol melalui pengikatan data.

public class StudentRecord : ViewModelBase
{
private int _id;
public int Id
{
get
{
return _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");
}
}

private string _address;
public string Address
{
get
{
return _address;
}
set
{
_address = value;
OnPropertyChanged("Address");
}
}

private string _contact;
public string Contact
{
get
{
return _contact;
}
set
{
_contact = value;
OnPropertyChanged("Contact");
}
}

private ObservableCollection<StudentRecord> _studentRecords;
public ObservableCollection<StudentRecord> StudentRecords
{
get
{
return _studentRecords;
}
set
{
_studentRecords = value;
OnPropertyChanged("StudentRecords");
}
}

private void StudentModels_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("StudentRecords");
}
}

4. Tambahkan kelas repositori di dalam Folder DataAccess yang melakukan operasi CRUD ke database.

public class StudentRepository
{
private StudentEntities studentContext = null;

public StudentRepository()
{
studentContext = new StudentEntities();
}

public Student Get(int id)
{
return studentContext.Students.Find(id);
}

public List<Student> GetAll()
{
return studentContext.Students.ToList();
}

public void AddStudent(Student student)
{
if (student != null)
{
studentContext.Students.Add(student);
studentContext.SaveChanges();
}
}

public void UpdateStudent(Student student)
{
var studentFind = this.Get(student.ID);
if (studentFind != null)
{
studentFind.Name = student.Name;
studentFind.Contact = student.Contact;
studentFind.Age = student.Age;
studentFind.Address = student.Address;
studentContext.SaveChanges();
}
}

public void RemoveStudent(int id)
{
var studObj = studentContext.Students.Find(id);
if (studObj != null)
{
studentContext.Students.Remove(studObj);
studentContext.SaveChanges();
}
}
}

AKU AKU AKU. Mengkodekan Kelas ViewModel

1. Tambahkan kelas ViewModelBase yang mengimplementasikan antarmuka INofifyPropertyChanged. Antarmuka ini pada dasarnya memberi tahu klien yang mengikat bahwa nilai properti telah diperbarui. Kelas ini diwarisi oleh model StudentRecord yang propertinya digunakan dalam pengikatan data dan memerlukan semacam pemberitahuan ketika nilai properti telah diubah.

public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2. Berikutnya adalah menambahkan kelas RelayCommand yang mengimplementasikan antarmuka ICommand. Perintah digunakan untuk menangani kejadian di WPF sehubungan dengan Pola Arsitektur MVVM. Satu-satunya tujuan dari sebuah perintah adalah untuk menyampaikan atau mendistribusikan fungsinya ke objek lain dengan memanggil delegasi. Nilai pengembalian default untuk metode CanExecute adalah benar. Penjelasan yang bagus tentang penjelasan tentang kelas RelayCommand stackoverflow.com.

public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;

public RelayCommand(Action<object> execute)
: this(execute, null)
{
}

public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}

public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}

public void Execute(object parameter)
{
_execute(parameter);
}
}
3. Terakhir adalah membuat kelas ViewModel yang melakukan perintah pengikatan tombol yang kemudian memanggil metode khusus yang menangani operasi CRUD dan memperbarui nilai properti. Contohnya adalah SaveCommand yang terikat dengan tombol Simpan dalam tampilan. Ketika tombol simpan diklik, perintah simpan kemudian mengeksekusi metode SaveData () dan menyimpan informasi ke database dan kemudian memuat ulang semuanya ke objek Observable yang merupakan ItemSource dari DataGrid. Penjelasan rinci dan panjang tentang apa yang dilakukan MVVM disajikan di sini Aplikasi WPF Dengan Pola Desain Model-View-ViewModel. Kelas ViewModel masih dapat difaktorkan ulang seperti menempatkan perintah dan entitas ke dalam setiap kelas yang berbeda atau lebih. Tetapi untuk demo ini, saya akhirnya meletakkan semuanya di sini.

public class StudentViewModel
{
private ICommand _saveCommand;
private ICommand _resetCommand;
private ICommand _editCommand;
private ICommand _deleteCommand;
private StudentRepository _repository;
private Student _studentEntity = null;
public StudentRecord StudentRecord { get; set; }
public StudentEntities StudentEntities { get; set; }

public ICommand ResetCommand
{
get
{
if (_resetCommand == null)
_resetCommand = new RelayCommand(param => ResetData(), null);

return _resetCommand;
}
}

public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
_saveCommand = new RelayCommand(param => SaveData(), null);

return _saveCommand;
}
}

public ICommand EditCommand
{
get
{
if (_editCommand == null)
_editCommand = new RelayCommand(param => EditData((int)param), null);

return _editCommand;
}
}

public ICommand DeleteCommand
{
get
{
if (_deleteCommand == null)
_deleteCommand = new RelayCommand(param => DeleteStudent((int)param), null);

return _deleteCommand;
}
}

public StudentViewModel()
{
_studentEntity = new Student();
_repository = new StudentRepository();
StudentRecord = new StudentRecord();
GetAll();
}

public void ResetData()
{
StudentRecord.Name = string.Empty;
StudentRecord.Id = 0;
StudentRecord.Address = string.Empty;
StudentRecord.Contact = string.Empty;
StudentRecord.Age = 0;
}

public void DeleteStudent(int id)
{
if (MessageBox.Show("Confirm delete of this record?", "Student", MessageBoxButton.YesNo)
== MessageBoxResult.Yes)
{
try
{
_repository.RemoveStudent(id);
MessageBox.Show("Record successfully deleted.");
}
catch (Exception ex)
{
MessageBox.Show("Error occured while saving. " + ex.InnerException);
}
finally
{
GetAll();
}
}
}

public void SaveData()
{
if (StudentRecord != null)
{
_studentEntity.Name = StudentRecord.Name;
_studentEntity.Age = StudentRecord.Age;
_studentEntity.Address = StudentRecord.Address;
_studentEntity.Contact = StudentRecord.Contact;

try
{
if (StudentRecord.Id <= 0)
{
_repository.AddStudent(_studentEntity);
MessageBox.Show("New record successfully saved.");
}
else
{
_studentEntity.ID = StudentRecord.Id;
_repository.UpdateStudent(_studentEntity);
MessageBox.Show("Record successfully updated.");
}
}
catch (Exception ex)
{
MessageBox.Show("Error occured while saving. " + ex.InnerException);
}
finally
{
GetAll();
ResetData();
}
}
}

public void EditData(int id)
{
var model = _repository.Get(id);
StudentRecord.Id = model.ID;
StudentRecord.Name = model.Name;
StudentRecord.Age = (int)model.Age;
StudentRecord.Address = model.Address;
StudentRecord.Contact = model.Contact;
}

public void GetAll()
{
StudentRecord.StudentRecords = new ObservableCollection<StudentRecord>();
_repository.GetAll().ForEach(data => StudentRecord.StudentRecords.Add(new StudentRecord()
{
Id = data.ID,
Name = data.Name,
Address = data.Address,
Age = Convert.ToInt32(data.Age),
Contact = data.Contact
}));
}
}

IV. Databinding dan View

1. Terakhir adalah tampilan. Pindahkan halaman MainWindow ke dalam folder View proyek. Dalam metode konstruktor, setel kelas DataContext dengan kelas StudentViewModel. Anda dapat memilih untuk mengatur DataContext melalui XAML.

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new StudentViewModel();
}
}
2. Berikutnya adalah menambahkan beberapa kontrol seperti kotak teks untuk menerima input, tombol untuk memicu kejadian dan kontrol DataGrid untuk menampilkan seluruh informasi yang diperbarui dari database. Kontrol ini telah direkatkan ke kelas ViewModel melalui Mengikat Properti. Kontrol input dikelompokkan dalam panel GroupBox, sedangkan tombol Save dan Reset berada di dalam wadah StackPanel. DataGrid juga berada di dalam wadah StackPanel dan masing-masing wadah ini disusun secara horizontal di dalam wadah induk StackPanel.

<Window x:Class="MVVMDemo.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MVVMDemo.View"
mc:Ignorable="d"
Title="Basic Create Update Delete With MVVM"
Height="500" Width="600">
<StackPanel Orientation="Vertical">
<GroupBox Header="Student Form" Margin="10">
<Grid Height="150">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Name" HorizontalAlignment="Left"
VerticalContentAlignment="Center" Grid.Column="0" Grid.Row="0"/>
<TextBox Grid.Row="0" Grid.Column="1" x:Name="TextBoxName" Height="27"
Text="{Binding Path=StudentRecord.Name, Mode=TwoWay}" Margin="5" Width="300" HorizontalAlignment="Left"/>
<Label Content="Age" HorizontalAlignment="Left" VerticalContentAlignment="Center"
Grid.Row="1" Grid.Column="0"/>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="TextBoxAge" Height="27"
Text="{Binding Path=StudentRecord.Age, Mode=TwoWay}" Margin="5" Width="70" HorizontalAlignment="Left"/>
<TextBlock Grid.Row="1" Grid.Column="1" x:Name="TextBlockId"
Visibility="Hidden" Text="{Binding Path=StudentRecord.Id, Mode=TwoWay}"/>
<Label Content="Address" HorizontalAlignment="Left" VerticalContentAlignment="Center"
Grid.Row="2" Grid.Column="0" />
<TextBox Grid.Row="2" Grid.Column="1" x:Name="TextBoxAddress" Height="27"
Text="{Binding Path=StudentRecord.Address, Mode=TwoWay}" Margin="5" Width="300" HorizontalAlignment="Left"/>
<Label Content="Contact" HorizontalAlignment="Left" VerticalContentAlignment="Center"
Grid.Row="3" Grid.Column="0" />
<TextBox Grid.Row="3" Grid.Column="1" x:Name="TextBoxContact" Height="27"
Text="{Binding Path=StudentRecord.Contact, Mode=TwoWay}" Margin="5" Width="300" HorizontalAlignment="Left"/>
</Grid>
</GroupBox>
<StackPanel Height="40" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="ButtonSave" Content="Save" Height="30" Width="80"
Command="{Binding SaveCommand}"/>
<Button x:Name="ButtonCancel" Content="Cancel" Height="30" Width="80"
Command="{Binding ResetCommand}" Margin="5,0,10,0"/>
</StackPanel>
<StackPanel Height="210">
<DataGrid x:Name="DataGridStudents" AutoGenerateColumns="False"
ItemsSource="{Binding StudentRecord.StudentRecords}" CanUserAddRows="False" Height="200" Margin="10">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Id}" Visibility="Hidden"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" Width="100" IsReadOnly="True"/>
<DataGridTextColumn Header="Age" Binding="{Binding Path=Age}" Width="50" IsReadOnly="True"/>
<DataGridTextColumn Header="Address" Binding="{Binding Path=Address}" Width="180" IsReadOnly="True"/>
<DataGridTextColumn Header="Contact" Binding="{Binding Path=Contact}" Width="125" IsReadOnly="True"/>
<DataGridTemplateColumn Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Select" x:Name="ButtonEdit" CommandParameter="{Binding Path=Id}"
Command="{Binding Path=DataContext.EditCommand,RelativeSource={RelativeSource FindAncestor,
AncestorType=Window}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="50">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Delete" x:Name="ButtonDelete" CommandParameter="{Binding Path=Id}"
Command="{Binding Path=DataContext.DeleteCommand, RelativeSource={RelativeSource FindAncestor,
AncestorType=Window}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</StackPanel>
</Window>

Keluaran

Pos terkait

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *