Tugas 4 PBKK - A
- Visual Studio dengan Installation Package .NET Desktop Development
- Link referensi untuk code awal dari program: Menerapkan MVVM di Windows Presentation Foundation (WPF)
- Link referensi untuk melakukan koneksi database: Connector/NET for Entity Framework - Entity Framework 6 Support
Program Awal
Setelah mengikuti seluruh petunjuk pada referensi pertama, program sudah dapat berjalan, akan tetapi masih belum dapat menyimpan data dikarenakan database belum dapat ter-connect. Kumpulan potongan code yang dibutuhkan untuk pengerjaan adalah sebagai berikut:
App.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <entityFramework> <providers> <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" /> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> <connectionStrings> <add name="LatihanContext" connectionString="server=localhost; database=latihan; uid=meong; password=root" providerName="MySql.Data.MySqlClient" /> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> </startup> </configuration>
HistoryContext.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity.Migrations.History; using System.Data.Common; using System.Data.Entity; namespace WpfApp2 { public class MyHistoryContext : HistoryContext { public MyHistoryContext(DbConnection dbConnection, string defaultSchema) : base(dbConnection, defaultSchema) { } protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasMaxLength(100).IsRequired(); modelBuilder.Entity<HistoryRow>().Property(p => p.ContextKey).HasMaxLength(200).IsRequired(); } } public class ModelConfiguration : DbConfiguration { public ModelConfiguration() { SetHistoryContext("MySql.Data.MySqlClient", (c, s) => new MyHistoryContext(c, s)); } } }
ItemPenjualan.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace WpfApp2 { public class ItemPenjualan { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id { get; set; } [StringLength(50)] public string NamaBarang { get; set; } public ItemPenjualan() { DiskonPersen = 0; } 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); } } }
ItemPenjualanViewModel.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel; using System.Windows.Input; using System.Windows; namespace WpfApp2 { class ItemPenjualanViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private ItemPenjualan model; private ICommand simpanCommand; 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; } } public ICommand SimpanCommand { get { if (this.simpanCommand == null) { this.simpanCommand = new SimpanCommand(this); } return this.simpanCommand; } } } class SimpanCommand : ICommand { private ItemPenjualanViewModel viewModel; public SimpanCommand(ItemPenjualanViewModel viewModel) { this.viewModel = viewModel; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return viewModel.Model.Total() > 0; } public void Execute(object parameter) { using (var db = new LatihanContext()) { db.Database.Log = Console.Write; db.DaftarItemPenjualan.Add(viewModel.Model); db.SaveChanges(); MessageBox.Show("Data berhasil disimpan ke database"); } } } }
Mainwindow.xaml
<Window x:Class="WpfApp2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 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="Validation.ErrorTemplate"> <Setter.Value> <ControlTemplate> <StackPanel Orientation="Horizontal"> <AdornedElementPlaceholder /> <TextBlock Text="Perlu diperbaiki!" Padding="3" Foreground="Red" /> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="Language" Value="in-IN" /> <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> </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 Height="23" HorizontalAlignment="Stretch" Margin="112,55,12,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=NamaBarang}" /> <Label Content="Jumlah:" Height="27" HorizontalAlignment="Left" Margin="1,86,0,0" Name="label3" VerticalAlignment="Top" Width="106" HorizontalContentAlignment="Right" /> <TextBox Height="23" HorizontalAlignment="Left" Margin="113,90,0,0" Name="textBox2" VerticalAlignment="Top" Width="62" Text="{Binding Path=Jumlah, StringFormat={}{0:#.0}}" /> <Label Content="Harga:" Height="28" HorizontalAlignment="Left" Margin="12,122,0,0" Name="label4" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="95" /> <TextBox Height="23" HorizontalAlignment="Left" Margin="113,127,0,0" Name="textBox3" VerticalAlignment="Top" Width="124" Text="{Binding Path=Harga, StringFormat={}{0:C}}" /> <Button Content="Simpan" Height="27" HorizontalAlignment="Left" Margin="207,228,0,0" Name="button1" VerticalAlignment="Top" Width="82" Command="{Binding SimpanCommand}" /> <Label Content="Diskon (%):" Height="33" HorizontalAlignment="Left" Margin="12,161,0,0" Name="label5" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="95" /> <TextBox Height="23" HorizontalAlignment="Left" Margin="113,165,0,0" Name="textBox4" VerticalAlignment="Top" Width="62" Text="{Binding Path=DiskonPersen, StringFormat={}{0:#.#}}" /> <Label Content="Total:" Height="33" HorizontalAlignment="Left" Margin="12,194,0,0" Name="label6" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="95" /> <Label Content="{Binding Path=Total}" 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>
persistence context.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity.Migrations.History; using System.Data.Common; using System.Data.Entity; namespace WpfApp2 { class LatihanContext : DbContext { public DbSet<ItemPenjualan> DaftarItemPenjualan { get; set; } } }
Koneksi ke Database
Persiapan yang harus dilakukan:
- Meng-install aplikasi - aplikasi berikut:
- MySQL Server
- MySQL for Visual Studio
- MySQL Connector for .NET
- Melakukan instalasi package untuk package - package yang belum terpasang sebelumnya, dapat dilakukan melalui NuGet Package Manager. Package MySql.Data.EntityFramework akan digunakan untuk melakukan koneksi ke database.
Langkah - langkah untuk menghubungkan aplikasi dengan database:
- Lakukan perubahan pada App.Config pada line - line berikut:
- Providers
- Connection Strings (Menyesuaikan dengan Username, Password, dan Port pada MySQL Server yang telah di-install sebelumnya
- Melakukan perubahan pada persistence context.cs menjadi seperti berikut:
- Melalui Package Manager Console, jalankan command berikut secara berurutan:
- Enable-Migrations
- Add-Migrations
- Setelah command Add-Migrations dijalankan, akan diminta input berupa parameter name. Inputkan nama bebas saat name diminta
- Update-Database
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/> </startup> <connectionStrings> <add name="LatihanContext" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=latihan;uid=root;password=root"/> </connectionStrings> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/> <providers> <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework"/> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/> </providers> </entityFramework> </configuration>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity.Migrations.History; using System.Data.Common; using MySql.Data.EntityFramework; using System.Data.Entity; namespace WpfApp2 { [DbConfigurationType(typeof(MySqlEFConfiguration))] class LatihanContext : DbContext { public DbSet<ItemPenjualan> DaftarItemPenjualan { get; set; } } }
Demo Program:
Comments
Post a Comment