This article will cover how to create a basic application and contact page using WPF (Windows Presentation Foundation). WPF is based on the .NET Framework and provides powerful UI design and data binding capabilities. We will develop a simple contact management application.
1. What is WPF?
WPF is a UI framework provided by Microsoft that helps build complex desktop applications. WPF uses XAML (Extensible Application Markup Language) to define the user interface and allows you to implement application logic using .NET languages.
Key advantages of WPF include:
- Excellent data binding capabilities.
- Powerful graphics and animation rendering.
- Support for MVVM (Model-View-ViewModel) design pattern.
- Providing a variety of UI controls.
2. Project Setup
Let’s explain how to create a WPF application in Visual Studio.
- Run Visual Studio and select “Create a new project”.
- Select WPF Application and name the project “ContactManager”.
- Once the project is created, you will find the preprovided MainWindow.xaml file.
3. Basic UI Layout using XAML
XAML is the markup language that defines the user interface in WPF. Below is the XAML code that sets up a basic contact management UI.
<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 Management" Height="350" Width="525">
<Grid>
<TextBox x:Name="txtName" Width="200" Height="25" Margin="10" PlaceholderText="Enter Name"/>
<TextBox x:Name="txtPhone" Width="200" Height="25" Margin="10,40,10,10" PlaceholderText="Enter Phone Number"/>
<Button x:Name="btnAdd" Content="Add" Width="75" Height="25" Margin="10,80,10,10" Click="BtnAdd_Click"/>
<ListBox x:Name="lstContacts" Margin="220,10,10,10"></ListBox>
</Grid>
</Window>
The above XAML code includes two text boxes for entering a name and phone number, a list box to display the contact list, and a button to add contacts.
4. Implementing Business Logic with C#
Now let’s write the business logic for the UI created with XAML. Add the following code to the MainWindow.xaml.cs file.
using System;
using System.Collections.Generic;
using System.Windows;
namespace ContactManager
{
public partial class MainWindow : Window
{
private List<Contact> contacts = new List<Contact>();
public MainWindow()
{
InitializeComponent();
}
private void BtnAdd_Click(object sender, RoutedEventArgs e)
{
var name = txtName.Text;
var phone = txtPhone.Text;
if (!string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(phone))
{
var contact = new Contact { Name = name, PhoneNumber = phone };
contacts.Add(contact);
UpdateContactList();
ClearInputs();
}
else
{
MessageBox.Show("Please enter name and phone number.");
}
}
private void UpdateContactList()
{
lstContacts.Items.Clear();
foreach (var contact in contacts)
{
lstContacts.Items.Add(contact.ToString());
}
}
private void ClearInputs()
{
txtName.Clear();
txtPhone.Clear();
}
}
public class Contact
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
public override string ToString()
{
return $"{Name} ({PhoneNumber})";
}
}
}
This code enables the user to input a name and phone number and add the contact to the list when the ‘Add’ button is clicked. It checks that the input values are not empty, updates the contact list, and clears the input fields.
5. Applying the MVVM Pattern
Now, let’s implement the MVVM pattern. MVVM is a design pattern that increases maintainability and testability in WPF applications. We will use the following structure:
- Model: Data structure and business logic.
- View: UI layout.
- ViewModel: Manages the connection and data binding between View and Model.
5.1. Model Class
public class Contact
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
public override string ToString()
{
return $"{Name} ({PhoneNumber})";
}
}
5.2. ViewModel Class
using System.Collections.ObjectModel;
using System.Windows.Input;
public class ContactViewModel : BaseViewModel
{
public ObservableCollection<Contact> Contacts { get; set; } = new ObservableCollection<Contact>();
private string name;
private string phoneNumber;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged(); }
}
public string PhoneNumber
{
get { return phoneNumber; }
set { phoneNumber = value; OnPropertyChanged(); }
}
public ICommand AddCommand { get; set; }
public ContactViewModel()
{
AddCommand = new RelayCommand(AddContact);
}
private void AddContact()
{
if (!string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(PhoneNumber))
{
var contact = new Contact { Name = Name, PhoneNumber = PhoneNumber };
Contacts.Add(contact);
ClearInputs();
}
}
private void ClearInputs()
{
Name = string.Empty;
PhoneNumber = string.Empty;
}
}
5.3. BaseViewModel Class
using System.ComponentModel;
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
5.4. RelayCommand Class
using System;
using System.Windows.Input;
public class RelayCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute();
}
public void Execute(object parameter)
{
execute();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
5.5. View Update
Now we will modify MainWindow.xaml to apply ViewModel and data binding:
<Window x:Class="ContactManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContactManager"
Title="Contact Management" Height="350" Width="525">
<Window.DataContext>
<local:ContactViewModel />
</Window.DataContext>
<Grid>
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Width="200" Height="25" Margin="10" PlaceholderText="Enter Name"/>
<TextBox Text="{Binding PhoneNumber, UpdateSourceTrigger=PropertyChanged}" Width="200" Height="25" Margin="10,40,10,10" PlaceholderText="Enter Phone Number"/>
<Button Command="{Binding AddCommand}" Content="Add" Width="75" Height="25" Margin="10,80,10,10"/>
<ListBox ItemsSource="{Binding Contacts}" Margin="220,10,10,10">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
6. Check the Results
When you run the application, the user interface will be displayed. Enter the name and phone number and click the ‘Add’ button to add a contact. The contact should be added to the list, and you will experience cleaner and more maintainable code compared to using control structures without the MVVM pattern.
7. Conclusion
In this tutorial, we explored how to create a basic contact management application using WPF. We demonstrated how applying the MVVM pattern in WPF can enhance code reusability and testability. In the future, try adding more complex features while utilizing various capabilities of WPF.
8. References
WPF is an evolving technology. Continue learning and practicing to become a better developer.