تطوير تطبيق WPF متقدم لتنفيذ CRUD باستخدام SQLite و#C مع نمط MVVM
مقدمة
نمط MVVM هو تصميم شائع في تطوير تطبيقات WPF حيث يُفصل الكود المتعلق بالواجهة (View) عن المنطق الخاص بالبيانات (Model) والربط بينهما (ViewModel). في هذا الدليل، سنقوم بإنشاء تطبيق CRUD مع SQLite يتبع نمط MVVM لتحسين القابلية للصيانة.
المتطلبات
- Visual Studio (أو أي بيئة تطوير تدعم #C وWPF)
- مكتبة
System.Data.SQLite
- المعرفة الأساسية بنمط MVVM
الخطوة 1: إنشاء مشروع WPF جديد
- افتح Visual Studio.
- اختر “مشروع جديد” من القائمة.
- اختر قالب WPF App (.NET Core) أو WPF App (.NET Framework).
- قم بتسمية المشروع، وحدد موقع الحفظ، ثم انقر على “إنشاء”.
الخطوة 2: إضافة مكتبة SQLite عبر NuGet
- انقر بزر الماوس الأيمن على المشروع في نافذة Solution Explorer.
- اختر “إدارة الحزم باستخدام NuGet”.
- ابحث عن System.Data.SQLite وقم بتثبيتها.
الخطوة 3: إعداد بنية المشروع باستخدام نمط MVVM
- أنشئ مجلدات جديدة في مشروعك: Models، ViewModels، Views.
- في مجلد Models، قم بتعريف نموذج البيانات (Model) الذي يمثل الجدول في قاعدة البيانات.
- في مجلد ViewModels، قم بتعريف ViewModel الذي يحتوي على المنطق الخاص بالتفاعل مع البيانات.
- في مجلد Views، قم بتعريف واجهة المستخدم التي ستتفاعل مع ViewModel عبر Binding.
الخطوة 4: إنشاء نموذج البيانات (Model)
قم بإنشاء فئة User
في مجلد Models. ستحتوي هذه الفئة على الخصائص التي تمثل بيانات المستخدم، مع تنفيذ واجهة INotifyPropertyChanged
لدعم التحديث التلقائي لواجهة المستخدم، وواجهة IDataErrorInfo
للتحقق من صحة البيانات.
namespace WpfAppWithSQLite.Models
{
public class User : INotifyPropertyChanged, IDataErrorInfo
{
private int id;
private string name;
private int age;
public int Id
{
get => id;
set
{
id = value;
OnPropertyChanged(nameof(Id));
}
}
public string Name
{
get => name;
set
{
name = value;
OnPropertyChanged(nameof(Name));
}
}
public int Age
{
get => age;
set
{
age = value;
OnPropertyChanged(nameof(Age));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// Validation logic
public string Error => null;
public string this[string columnName]
{
get
{
string result = null;
if (columnName == nameof(Name))
{
if (string.IsNullOrWhiteSpace(Name))
result = "Name is required.";
}
else if (columnName == nameof(Age))
{
if (Age <= 0)
result = "Age must be greater than zero.";
}
return result;
}
}
}
}
User
هي فئة تمثل كيان المستخدم. تحتوي على الخصائص Id
, Name
, و Age
.
يتم استخدام INotifyPropertyChanged
لتحديث واجهة المستخدم تلقائيًا عند تغيير قيمة خاصية ما.
يتم استخدام IDataErrorInfo
للتحقق من صحة البيانات، مثل التأكد من أن الاسم ليس فارغًا وأن العمر أكبر من الصفر.
الخطوة 5: إنشاء ViewModel
قم بإنشاء فئة UserViewModel
في مجلد ViewModels. هذا الجزء سيتحكم في المنطق الخاص بالتفاعل مع البيانات وتحديث واجهة المستخدم.
using System.Collections.ObjectModel;
using System.Windows.Input;
using WpfAppWithSQLite.Models;
namespace WpfAppWithSQLite.ViewModels
{
public class UserViewModel : INotifyPropertyChanged
{
public ObservableCollection<User> Users { get; set; }
private User selectedUser;
public User SelectedUser
{
get => selectedUser;
set
{
selectedUser = value;
OnPropertyChanged(nameof(SelectedUser));
}
}
public ICommand AddUserCommand { get; }
public ICommand UpdateUserCommand { get; }
public ICommand DeleteUserCommand { get; }
public UserViewModel()
{
Users = new ObservableCollection<User>(UserRepository.GetAllUsers());
AddUserCommand = new RelayCommand(AddUser);
UpdateUserCommand = new RelayCommand(UpdateUser, CanModifyUser);
DeleteUserCommand = new RelayCommand(DeleteUser, CanModifyUser);
}
private void AddUser(object parameter)
{
var newUser = new User { Name = "New User", Age = 18 };
UserRepository.AddUser(newUser.Name, newUser.Age);
Users.Add(newUser);
}
private void UpdateUser(object parameter)
{
if (SelectedUser != null)
{
UserRepository.UpdateUser(SelectedUser.Id, SelectedUser.Name, SelectedUser.Age);
}
}
private void DeleteUser(object parameter)
{
if (SelectedUser != null)
{
UserRepository.DeleteUser(SelectedUser.Id);
Users.Remove(SelectedUser);
}
}
private bool CanModifyUser(object parameter) => SelectedUser != null;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RelayCommand : ICommand
{
private readonly Action<object> execute;
private readonly Predicate<object> canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => canExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter) => execute(parameter);
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
UserViewModel
يحتوي على مجموعة Users
من نوع ObservableCollection<User>
لعرض المستخدمين في واجهة المستخدم.
SelectedUser
هي الخاصية المرتبطة بالمستخدم المحدد في القائمة.
الأوامر AddUserCommand
, UpdateUserCommand
, و DeleteUserCommand
تستخدم لتنفيذ عمليات CRUD.
RelayCommand
هو كلاس يساعد في تنفيذ الأوامر بمرونة في WPF.
الخطوة 6: إنشاء واجهة المستخدم (View)
افتح ملف MainWindow.xaml
في مجلد Views وأنشئ الواجهة التالية التي تحتوي على جدول لعرض بيانات المستخدمين مع أزرار لإضافة، تحديث، وحذف المستخدمين.
<Window x:Class="WpfAppWithSQLite.Views.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:WpfAppWithSQLite.Views"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid ItemsSource="{Binding Users}" SelectedItem="{Binding SelectedUser}" AutoGenerateColumns="False" Margin="10">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Age" Binding="{Binding Age}" />
</DataGrid.Columns>
</DataGrid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10">
<Button Content="Add" Command="{Binding AddUserCommand}" Margin="5"/>
<Button Content="Update" Command="{Binding UpdateUserCommand}" Margin="5"/>
<Button Content="Delete" Command="{Binding DeleteUserCommand}" Margin="5"/>
</StackPanel>
</Grid>
</Window>
DataGrid
يعرض قائمة المستخدمين مع أعمدة لعرض الـ Id
, Name
, و Age
.
StackPanel
يحتوي على أزرار لتنفيذ عمليات CRUD باستخدام الأوامر المرتبطة بـ ViewModel.
الخطوة 7: ربط العرض View بـ ViewModel
- في ملف
MainWindow.xaml.cs
، قم بتعيينDataContext
إلىUserViewModel
.
using System.Windows;
using WpfAppWithSQLite.ViewModels;
namespace WpfAppWithSQLite.Views
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new UserViewModel();
}
}
}
الخطوة 8: تنفيذ عمليات CRUD في قاعدة البيانات
أنشئ فئة UserRepository
في مجلد Models لتنفيذ عمليات CRUD على قاعدة بيانات SQLite.
using System.Collections.Generic;
using System.Data.SQLite;
namespace WpfAppWithSQLite.Models
{
public static class UserRepository
{
private static string connectionString = "Data Source=users.db;Version=3;";
public static IEnumerable<User> GetAllUsers()
{
var users = new List<User>();
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
var command = new SQLiteCommand("SELECT * FROM Users", connection);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
users.Add(new User
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Age = reader.GetInt32(2)
});
}
}
}
return users;
}
public static void AddUser(string name, int age)
{
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
var command = new SQLiteCommand("INSERT INTO Users (Name, Age) VALUES (@Name, @Age)", connection);
command.Parameters.AddWithValue("@Name", name);
command.Parameters.AddWithValue("@Age", age);
command.ExecuteNonQuery();
}
}
public static void UpdateUser(int id, string name, int age)
{
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
var command = new SQLiteCommand("UPDATE Users SET Name = @Name, Age = @Age WHERE Id = @Id", connection);
command.Parameters.AddWithValue("@Id", id);
command.Parameters.AddWithValue("@Name", name);
command.Parameters.AddWithValue("@Age", age);
command.ExecuteNonQuery();
}
}
public static void DeleteUser(int id)
{
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
var command = new SQLiteCommand("DELETE FROM Users WHERE Id = @Id", connection);
command.Parameters.AddWithValue("@Id", id);
command.ExecuteNonQuery();
}
}
}
}
الخاتمة
لقد قمنا في هذا الدليل بإنشاء تطبيق WPF متقدم لتنفيذ عمليات CRUD باستخدام SQLite ونمط MVVM. بدأنا بإنشاء مشروع WPF، ثم أضفنا مكتبة SQLite، وأنشأنا بنية المشروع باستخدام نمط MVVM، وقمنا بتعريف نموذج البيانات وViewModel وواجهة المستخدم. أخيرًا، قمنا بتنفيذ عمليات CRUD على قاعدة بيانات SQLite. باستخدام هذا النهج، يمكننا فصل المنطق عن العرض، مما يجعل التطبيق أسهل في الصيانة والتطوير.
اترك تعليقاً