تطوير تطبيق سطح المكتب WPF لإدارة جهات الاتصال: بناء، تصدير واستيراد البيانات باستخدام MVVM و Entity Framework
المقدمة
في هذا المشروع، ستتعلم كيفية بناء تطبيق لإدارة جهات الاتصال باستخدام WPF وMVVM. سنضيف ميزات متقدمة مثل تصدير البيانات إلى ملفات CSV واستيرادها منها، بالإضافة إلى تحسين واجهة المستخدم من خلال تطبيق فلاتر وفرز البيانات.
الخطوات الأساسية لبناء التطبيق
1. إنشاء هيكل المشروع في Visual Studio
- ابدأ مشروع WPF جديد: افتح Visual Studio، اختر
File > New > Project
، ثم اخترWPF App (.NET Core)
وقم بتسمية المشروع “ContactManager”. - في نافذة Solution Explorer، قم بإنشاء المجلدات التالية:
- Models: لتمثيل البيانات (جهات الاتصال).
- ViewModels: لإدارة منطق التطبيق.
- Views: لملفات واجهة المستخدم (XAML).
- Data: لكلاس DbContext الذي يمثل قاعدة البيانات.
- Helpers: لإنشاء الكلاس RelayCommand الذي سنستخدمه لربط الأوامر بالواجهة.
إنشاء RelayCommand Class
داخل مجلد Helpers، قم بإنشاء كلاس جديد باسم RelayCommand.cs. سيستخدم هذا الكلاس لتنفيذ الأوامر وربطها بواجهة المستخدم (XAML). إليك الكود الكامل:
using System;
using System.Windows.Input;
namespace ContactManager.Helpers
{
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
يتيح لك RelayCommand تنفيذ الأوامر وربطها بأحداث معينة في الواجهة، مما يجعل إدارة التفاعلات مع المستخدم أكثر مرونة في نموذج MVVM.
2. تصميم نموذج البيانات (Models)
قم بإنشاء مجلد باسم Models في المشروع. داخل هذا المجلد، قم بإنشاء ملف جديد: Contact.cs.
Contact.cs
namespace ContactManager.Models
{
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
}
3. إنشاء الـ ViewModel
قم بإنشاء مجلد باسم ViewModels داخل المشروع. هذا المجلد سيحتوي على الكلاس الذي يدير العمليات المنطقية للتطبيق. قم بإنشاء ملف باسم ContactViewModel.cs داخل المجلد.
ContactViewModel.cs
using ContactManager.Helpers;
using ContactManager.Models.ContactManager.Models;
using Microsoft.Win32; // For file dialogs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace ContactManager.ViewModels
{
public class ContactViewModel : INotifyPropertyChanged
{
private ObservableCollection<Contact> _contacts;
public ObservableCollection<Contact> Contacts
{
get { return _contacts; }
set { _contacts = value; OnPropertyChanged(); }
}
private Contact _selectedContact;
public Contact SelectedContact
{
get { return _selectedContact; }
set { _selectedContact = value; OnPropertyChanged(); }
}
private ContactDbContext _dbContext;
public ICommand AddContactCommand { get; }
public ICommand UpdateContactCommand { get; }
public ICommand DeleteContactCommand { get; }
public ICommand ExportContactsCommand { get; }
public ICommand ImportContactsCommand { get; }
public ContactViewModel()
{
_dbContext = new ContactDbContext();
Contacts = new ObservableCollection<Contact>(_dbContext.Contacts.ToList());
SelectedContact = new Contact(); // Initialize SelectedContact
AddContactCommand = new RelayCommand(AddContact);
UpdateContactCommand = new RelayCommand(UpdateContact, CanExecuteUpdateOrDelete);
DeleteContactCommand = new RelayCommand(DeleteContact, CanExecuteUpdateOrDelete);
ExportContactsCommand = new RelayCommand(ExportContacts);
ImportContactsCommand = new RelayCommand(ImportContacts);
}
private bool CanExecuteUpdateOrDelete(object parameter)
{
return SelectedContact != null;
}
private void AddContact(object parameter)
{
var newContact = new Contact
{
Name = SelectedContact.Name,
Email = SelectedContact.Email,
Phone = SelectedContact.Phone
};
_dbContext.Contacts.Add(newContact);
_dbContext.SaveChanges();
Contacts.Add(newContact);
// Reset SelectedContact for the next entry
SelectedContact = new Contact();
}
private void UpdateContact(object parameter)
{
if (SelectedContact == null) return;
var contactToUpdate = _dbContext.Contacts.FirstOrDefault(c => c.Id == SelectedContact.Id);
if (contactToUpdate != null)
{
contactToUpdate.Name = SelectedContact.Name;
contactToUpdate.Email = SelectedContact.Email;
contactToUpdate.Phone = SelectedContact.Phone;
_dbContext.SaveChanges();
}
}
private void DeleteContact(object parameter)
{
if (SelectedContact == null) return;
_dbContext.Contacts.Remove(SelectedContact);
_dbContext.SaveChanges();
Contacts.Remove(SelectedContact);
}
// تصدير جهات الاتصال إلى ملف CSV
private void ExportContacts(object parameter)
{
var saveFileDialog = new SaveFileDialog
{
Filter = "CSV files (*.csv)|*.csv",
FileName = "contacts.csv"
};
if (saveFileDialog.ShowDialog() == true)
{
using (var writer = new StreamWriter(saveFileDialog.FileName))
{
foreach (var contact in Contacts)
{
writer.WriteLine($"{contact.Name},{contact.Email},{contact.Phone}");
}
}
}
}
// استيراد جهات الاتصال من ملف CSV
private void ImportContacts(object parameter)
{
var openFileDialog = new OpenFileDialog
{
Filter = "CSV files (*.csv)|*.csv"
};
if (openFileDialog.ShowDialog() == true)
{
using (var reader = new StreamReader(openFileDialog.FileName))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
var contact = new Contact
{
Name = values[0],
Email = values[1],
Phone = values[2]
};
_dbContext.Contacts.Add(contact);
_dbContext.SaveChanges();
Contacts.Add(contact);
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
4. إعداد قاعدة البيانات باستخدام Entity Framework
للبدء باستخدام Entity Framework في مشروعك، تحتاج أولاً إلى تثبيت الحزمة اللازمة من NuGet. اتبع الخطوات التالية:
تثبيت Entity Framework
- افتح Package Manager Console في Visual Studio عبر القائمة:
.Tools > NuGet Package Manager > Package Manager Console
- قم بتنفيذ الأمر التالي لتثبيت Entity Framework Core:
Install-Package Microsoft.EntityFrameworkCore.Sqlite
- إذا كنت ترغب في استخدام أدوات Entity Framework لتطبيق الهجرات والتحديثات لقاعدة البيانات، قم بتنفيذ الأمر التالي أيضًا:
Install-Package Microsoft.EntityFrameworkCore.Tools
إنشاء قاعدة البيانات وتطبيق الهجرة تلقائيًا
بعد تثبيت الحزم، سنقوم بتعديل كلاس `ContactDbContext` لضمان إنشاء قاعدة البيانات وتطبيق أي هجرات عند بدء تشغيل التطبيق. سيساعدنا هذا على عدم الحاجة إلى نسخ ملف قاعدة البيانات في كل مرة نقوم بتشغيل التطبيق.
تعديل `ContactDbContext`:
قم بتحديث كود `ContactDbContext` لإضافة طريقة `Database.Migrate()` التي تقوم بإنشاء قاعدة البيانات وتطبيق الهجرات تلقائيًا عند بدء تشغيل التطبيق.
using Microsoft.EntityFrameworkCore;
using ContactManager.Models;
namespace ContactManager
{
public class ContactDbContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=contacts.db");
}
public ContactDbContext()
{
// Ensures the database is created and applies any pending migrations
Database.Migrate();
}
}
}
باستخدام Database.Migrate()
، يتأكد التطبيق من إنشاء قاعدة البيانات إذا لم تكن موجودة وتطبيق أي تغييرات مطلوبة، مما يلغي الحاجة إلى نسخ ملف قاعدة البيانات في كل مرة نقوم بتشغيل التطبيق.
5. تصميم واجهة المستخدم (Views)
الآن، ننتقل لتصميم واجهة المستخدم الأساسية
<Window x:Class="ContactManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Contact Manager" Height="500" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<!-- قائمة جهات الاتصال -->
<DataGrid ItemsSource="{Binding Contacts}" Grid.Column="0" AutoGenerateColumns="False" SelectedItem="{Binding SelectedContact}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Email" Binding="{Binding Email}" />
<DataGridTextColumn Header="Phone" Binding="{Binding Phone}" />
</DataGrid.Columns>
</DataGrid>
<!-- تفاصيل جهة الاتصال المختارة -->
<StackPanel Grid.Column="1" Margin="10">
<TextBlock Text="Details" FontSize="16" FontWeight="Bold" />
<TextBox Text="{Binding SelectedContact.Name, UpdateSourceTrigger=PropertyChanged}" Margin="0,10" />
<TextBox Text="{Binding SelectedContact.Email, UpdateSourceTrigger=PropertyChanged}" Margin="0,10" />
<TextBox Text="{Binding SelectedContact.Phone, UpdateSourceTrigger=PropertyChanged}" Margin="0,10" />
<!-- أزرار العمليات -->
<Button Content="Add Contact" Command="{Binding AddContactCommand}" Margin="0,10" /> <!-- زر إضافة جهة الاتصال -->
<Button Content="Update Contact" Command="{Binding UpdateContactCommand}" Margin="0,10" />
<Button Content="Delete Contact" Command="{Binding DeleteContactCommand}" Margin="0,10" />
<!-- زر تصدير واستيراد جهات الاتصال -->
<Button Content="Export Contacts" Command="{Binding ExportContactsCommand}" Margin="0,10" />
<Button Content="Import Contacts" Command="{Binding ImportContactsCommand}" Margin="0,10" />
</StackPanel>
</Grid>
</Window>
تشغيل التطبيق:
اضغط على F5
لتشغيل التطبيق.

يمكنك العثور على المشروع الكامل على GitHub من خلال الرابط التالي: WPF Contact Manager.
الخاتمة
في هذا المشروع، قمنا ببناء تطبيق لإدارة جهات الاتصال باستخدام WPF وMVVM. أضفنا ميزات تصدير البيانات إلى ملفات CSV واستيراد البيانات من مصادر خارجية، كما قمنا بتحسين واجهة المستخدم بإضافة عمليات لإضافة، تحديث، وحذف جهات الاتصال. قمنا أيضًا بتعديل التطبيق لضمان إنشاء قاعدة البيانات تلقائيًا وتطبيق أي هجرات عند بدء تشغيل التطبيق. يمكنك توسيع هذا المشروع بإضافة ميزات أخرى مثل البحث المتقدم أو التعامل مع مجموعات بيانات أكبر.
اترك تعليقاً