WPF .NET Framework : Penerapan MVVM di Windows Presentation Foundation

Kali ini saya akan mencoba untuk membuat aplikasi Item Penjualan sederhana menggunakan WPF dengan menerapkan arsitektur MVVM (Model View View Model). MVVM sendiri bisa dikatakan juga merupakan MVC (Model View Controller) yang memisahkan antara logic dengan GUI (Graphical User Interface). Untuk implementasinya sebagai berikut.

  • Membuat Project WPF. 
Hal Pertama yang harus kita lakukan adalah membuat project WPF atau Windows Presentation Form dimana setelah kita melakukan create maka akan terdapat file MainWindow.xaml yang merupakan file untuk GUI aplikasi kita.

 

  • Membuat Model

Sebagai model dibuatlah sebuah class baru dengan nama  ItemPenjualan. Untuk kode dari class ini sebagai berikut.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LatihanMVVM
{
public class ItemPenjualan
{
public ItemPenjualan()
{
DiskonPersen = 0;
}
public long Id { get; set; }
public string NamaBarang { get; set; }
public int Jumlah { get; set; }
public decimal Harga { get; set; }
public decimal DiskonPersen { get; set; }
public decimal Total()
{
decimal total = Jumlah * Harga;
return total - (DiskonPersen / 100 * total);
}
}
}

  • Melakukan desain GUI (view)
Pada file MainWindow.xaml tersebut, kita lakukan desain GUI dari aplikasi yang kita buat. Untuk contoh bisa dilihat oleh source code berikut ini.

<Window x:Class="LatihanMVVM.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:LatihanMVVM"
mc:Ignorable="d"
Title="MainWindow" Height="356" Width="528">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20" />
<Setter Property="FontFamily" Value="Myriad Pro" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF508FC4" Offset="0" />
<GradientStop Color="#FF6F94AD" Offset="1" />
<GradientStop Color="#FFC7F3FF" Offset="0.302" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF5252CE" Offset="0" />
<GradientStop Color="#FF0000DB" Offset="0.953" />
<GradientStop Color="#FF6363CB" Offset="0.337" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="FontSize" Value="14" />
</Style>
<Style TargetType="TextBox">
<Setter Property="Language" Value="id-ID" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="customBorder" Background="{TemplateBinding Background}" CornerRadius="5" BorderThickness="2" BorderBrush="Gray">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="customBorder" Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="#578EC9"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="False">
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<AdornedElementPlaceholder />
<TextBlock Text="Perlu diperbaiki!" Padding="3" Foreground="Red" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button">
<Setter Property="Background" Value="#DEF2FC" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontSize" Value="15"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="10" ShadowDepth="0" Color="#578EC9"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="customBorder" Background="{TemplateBinding Background}" CornerRadius="4" BorderThickness="2" BorderBrush="Gray">
<ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#2394CC" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Effect" Value="{x:Null}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Effect">
<Setter.Value>
<BlurEffect Radius="3" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Label Content="Nama Barang:" Height="29" HorizontalAlignment="Left" Margin="0,49,0,0" Name="label2" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="107" />
<TextBox Text="" Height="23" HorizontalAlignment="Stretch" Margin="112,55,12,0" Name="textBox1" VerticalAlignment="Top" />
<Label Content="Jumlah:" Height="27" HorizontalAlignment="Left" Margin="1,86,0,0" Name="label3" VerticalAlignment="Top" Width="106" HorizontalContentAlignment="Right" />
<TextBox Text="" Height="23" HorizontalAlignment="Left" Margin="113,90,0,0" Name="textBox2" VerticalAlignment="Top" Width="62" />
<Label Content="Harga:" Height="28" HorizontalAlignment="Left" Margin="12,122,0,0" Name="label4" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="95" />
<TextBox Text="" Height="23" HorizontalAlignment="Left" Margin="113,127,0,0" Name="textBox3" VerticalAlignment="Top" Width="124" />
<Button Content="Simpan" Height="27" HorizontalAlignment="Left" Margin="207,228,0,0" Name="button1" VerticalAlignment="Top" Width="82" />
<Label Content="Diskon (%):" Height="33" HorizontalAlignment="Left" Margin="12,161,0,0" Name="label5" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="95" />
<TextBox Text="" Height="23" HorizontalAlignment="Left" Margin="113,165,0,0" Name="textBox4" VerticalAlignment="Top" Width="62" />
<Label Content="Total:" Height="33" HorizontalAlignment="Left" Margin="12,194,0,0" Name="label6" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="95" />
<Label Content="" Height="28" HorizontalAlignment="Left" Margin="113,194,0,0" Name="label7" VerticalAlignment="Top" Width="402" />
<TextBlock Height="28" HorizontalAlignment="Stretch" Name="textBlock1" Text="Tambah Item Penjualan" VerticalAlignment="Top" TextAlignment="Center" Margin="0,12,0,0" />
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFB7CEFF" Offset="0.192" />
<GradientStop Color="White" Offset="1" />
<GradientStop Color="#FF1648AD" Offset="0" />
</LinearGradientBrush>
</Grid.Background>
</Grid>
</Window>
view raw MainWindow.xaml hosted with ❤ by GitHub

 Untuk hasilnya akan membentuk window yang kira-kira seperti gambar dibawah ini.


  • Membuat ViewModel

Karena model dan view telah selesai dibuat, maka kita akan membuat sebuah view model yaitu dengan membuat class baru bernama ItemPenjualanViewModel. Untuk kode pada class ini sebagai berikut.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LatihanMVVM
{
class ItemPenjualanViewModel : INotifyPropertyChanged
{
//System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
public event PropertyChangedEventHandler PropertyChanged;
private ItemPenjualan model;
public ItemPenjualanViewModel(ItemPenjualan itemPenjualan = null)
{
this.model = itemPenjualan ?? new ItemPenjualan();
}
public string NamaBarang
{
get { return model.NamaBarang; }
set
{
if (value != model.NamaBarang)
{
model.NamaBarang = value;
PropertyChanged(this, new PropertyChangedEventArgs("NamaBarang"));
}
}
}
public int Jumlah
{
get { return model.Jumlah; }
set
{
if (value != model.Jumlah)
{
model.Jumlah = value;
PropertyChanged(this, new PropertyChangedEventArgs("Jumlah"));
PropertyChanged(this, new PropertyChangedEventArgs("Total"));
}
}
}
public decimal Harga
{
get { return model.Harga; }
set
{
if (value != model.Harga)
{
model.Harga = value;
PropertyChanged(this, new PropertyChangedEventArgs("Harga"));
PropertyChanged(this, new PropertyChangedEventArgs("Total"));
}
}
}
public decimal DiskonPersen
{
get { return model.DiskonPersen; }
set
{
if (value != model.DiskonPersen)
{
model.DiskonPersen = value;
PropertyChanged(this, new PropertyChangedEventArgs("DiskonPersen"));
PropertyChanged(this, new PropertyChangedEventArgs("Total"));
}
}
}
public string Total
{
get
{
decimal? total = model.Total();
if (!total.HasValue)
{
return "-";
}
else
{
return total.Value.ToString("C");
}
}
}
public ItemPenjualan Model
{
get { return this.model; }
}
}
}

  • Melakukan Data Binding

Untuk menghubungkan antara model, view, dan view model perlu didefinisikan sebuah DataContext. Untuk implementasinya adalah dengan membuat MainWindow.xaml.cs sebagai berikut.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace LatihanMVVM
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ItemPenjualanViewModel();
}
}
}

Kemudian kita lakukan Data Binding dengan mengubah MainWindow.xaml menjadi sebagai berikut.

...
<Label Content="Nama Barang:" ... />
<TextBox Name="textBox1" ... Text="{Binding Path=NamaBarang}"/>
<Label Content="Jumlah:" ... />
<TextBox ... Text="{Binding Path=Jumlah, StringFormat={}{0:#,0}}"/>
<Label Content="Harga:" ... />
<TextBox ... Text="{Binding Path=Harga, StringFormat={}{0:C}}"/>
<Label Content="Diskon (%):" ... />
<TextBox ... Text="{Binding Path=DiskonPersen, StringFormat={}{0:#.#}}"/>
<Label Content="Total:" ... />
<Label .... Content="{Binding Path=Total}" />
...
view raw MainWindow.xaml hosted with ❤ by GitHub


Hasil dari aplikasi yang telah kita buat hingga saat ini menjadi sebagai berikut. 

Komentar

Postingan Populer