XAML Peak new feature in Visual Studio 2015


The latest version of the Visual Studio 2015 is bringing a lot of new features for WPF and XAML programming language. For this blog post I would like to share the XAML Peak Definition. Peak Definition is not new, the current version of Visual Studio 2013 supports peak definition only for C# and VB. Now we have the same functionality within XAML. Event more, in the Visual Studio 2015 peak definition is working in mixed mode, so you can reach any definition regladless of the programming languges (C#, VB or XAML).

XAML peak allows you to get definition or content of any name defined in the XAML code. For example lets see the following XAML code. Right click on the MainWindow class and choose “Peak Definition”:

peakxamlsl1

After the command is selected, the new inline window appears within xaml, and the user can easily see or change the code behind selected definition. Peak Definition works for any proper name in the XAML.

peakxamlsl2

Lets see more interesting thing. Peak Definition is very handy when you want to see or modify the defined style or control template. For Example if we right click on the Style defined resource and choose Peak Definition like the following picture:

peakxamlsl31

Inline window will appears and show the style implementation of the selected xaml element. This is very useful and long waited option of XAML editor:

 

peakxamlsl4

Inline windows are edited windows so you can edit or add new code without leaving xaml editor.

This is one of the plenty of the new features coming with the latest version of the Visual Studio 2015. More features in the coming post.

 

 

 

Advertisement

WPF i LINQ to SQL III dio, data validation


U prethodnom postu vidjeli smo na koji način možemo manipulirati podacima u smislu sortiranja, grupiranja, te filtriranja podataka. Za ovaj put prezentiraćemo validiranje podataka u WPF odnosno DataValidation. U WPF postoji predefinisan model validiranja podataka tako da svaki tip izveden iz IDataErrorInfo interfejsa podržava validiranje podataka.

Implementacija validacije podataka

Početak ovog posta baziran je na prethodnom primjeru, a potrebno je implementirari validiranje podataka za naš model podataka. Valdaciju podataka moguće je implementirati na različitim konceptialnim modelima aplikacije. U ovom poglavlju validaciju ćemo implementirati na nivou našeg modela baze podataka. Validacija će se sastojati u tome da kad god unesemo datum veći od 1. Januara 2009 godine u datum narudžbe informacija o nepravilnom unosu upozoravaće nas prilikom svakog gubljenja fokusa date kontrole na našem interfejsu. Obzirom da smo validaciju pretpostavili na nivou modela, potrebno je klasu Orders derivirati iz interfejsa IdataErrorInfo da bi iskoristili ugrađeni mehanizam u WPF.

Otvorimo datoteku NorthWindKlase.cs te definišimo parcijanu deklaraciju klase Orders na sljedeći način:

partial class Order : IDataErrorInfo
{
#region IDataErrorInfo Members
 public string Error
  {
   get { return null; }
  }
 public string this[string columnName]
  {
   get
    {
      if (columnName == "OrderDate")
         if (OrderDate > newDateTime(2009, 1, 1))
           return "Datum nije validan. Molimo ispravite datum.";
    return null;
   }
  }
#endregion
}

Klasa Order izvedena je iz dva interfejsa koja su definisana u dizajnerskog datoteci. U cs datoteci ovu klasu izvodimo iz još jednog interfejsa IdataErrorInfo. Ovaj interfejs obezbjedjuje implementaciju validacije podataka u WPF. Dvije implementacije je potrebno izvršiti i to za Property Error koja u ovom slučaju nije potrebna, a inače služi kada upravljamo sa više pogrešaka koje se mogu pojaviti u klasi Orders. Druga metoda je indexer u kojem prvo provjeravamo da li je vrijednost indexera posmatrani naziv kolone OrderDate. Zatim tekuću vrijednost provjeravamo, i ako vrijednost ne zadovoljava naše definisane kriterije vraćamo neprazan string koji u biti sadržava poruku pogreške.

Napomena: Kada u polju datuma ne postoji nikakva vrijednost (prazan string) ili vrijednost koja ne predstavlja datum, validacija takvih podataka je već implementirana tako da se takvi podaci neposmatraju ovom implementacijom. Naša validacija OrderDate kolone se sastoji u tome da ako smo definsiali datum koji je veći od 1. Januara 2009 godine, izbacuje se pogrešaka. Kada smo implementirali logiku validacije podataka u bussiness layeru, logiku je potrebno povezati sa UI kontrolama, odnosno sa TextBox kontrolom koja prikazuje OrderDate. Kada želimo da povežemo validaciju sa bilo kojom UI kontrlom postavljamo Property ValidatesOnDataErrors=True. Sa ovim je cijela implementacija validacije podataka iz bussiness layer povezana sa UI kontrolom.

Kada u ovoj fazi implementacije pokrenemo naš primjer i kad u polje OrderDate unesemo datum koji je veći od datuma 1. Januar 2009 godine, mehanizam validacije podataka se pokreće i dobijamo sljedeći sliku.

image_020720093C88EA80

Sa slike vidimo da je tekstualna kontrola Order Date promjenila boju ivice na crvenu. Ovo je standardni šablon koji se koristi kada se pokrene mehanizam validacije. Medjutim, sa crvenom bojom ivice mi ništa više ne znamo od pogreške. Za ovaj primjer implementirat ćemo šablon koji će tekst pogreške koji je uhvaćen u bussiness layeru prikazati kao tooltip naše kontrole. Da bi ovo implementirali potrebmo je definisati Stil validacije podataka. Stil validacije podataka definišemo na sljedeći način:

<!--Šablon validacije podataka-->
<Style  TargetType="TextBox">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="ToolTip"
                    Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                    Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>
</Style>

U biti gornja implementacija je implementacija stila za TextBox kontrolu koja u sebi sadrži implementaciju Triger (okidača) kad postoji pogreška u validaciji podataka. Kada se desi tada vrijednost ToolTipa date kontrole ima vrijednost teksta pogreške.

Sada kad pokrenemo aplikaciju te unesemo pogrešan datum kao u prethodnom primjeru, te odnesemo miša do date kontrole, pojavljuje se tooltip sa tekstom pogreške.

clip_02072009image002_6B0ECD95

Kada smo definisali Stil za validaciju podataka za textbox kontrolu nismo ga definisali sa ključnom nazivom (x:Key=”stilValidacije), što onda znači da dati stil automatski podešava sve textbox kontrole.

Sa ovim smo završili tutorijal o validaciji podataka.Izvorni kod za ovaj primjer možete skinuti sa ovog linka.

WPF i LINQ to SQL


U narednih nekoliko postova biće riječi o novoj microsoftovoj tehnologiji za razvoj windows aplikacija Windows Presentation Foundation, kao i razvoj aplikacija koje se oslanjaju na baze podataka preko LINQ to SQL i LINQ to Entity. Biće prikazani osnovni modeli aplikacije sa prikazom implementacije osnovnih CRUD operacija razvijani na WPF tehologiji.

Kratki uvod

WPF je nova tehnologija razvoja windows aplikacija bazira na DirectX grafičkoj biblioteci, umjesto klasičnih GDI aplikacija na kojim su se zasnivale sve dosadašnje microsoftove tehnologije. Ovim prelazom omogućen je razvoj windows grafičkih interfejsa na sličan način kako se to radi sa web aplikacijama. U tom smislu razvijen je novi programski jezik XAML (čitaj zaml) koji je sastavni dio .NET Frameworka. Sa razvojem XAML razvijen je novi skup programskih rješenja koja pomažu u dizajnu windows aplikacija nazvan Expression Studio. Ovaj paket aplikacija uključuje Expression Blend, Expresion Design i druge aplikacije kojim razvijamo GUI dok logiku ispod kontrola GUI-a razvijamo u klasičnim razvojnim alatima poput Visual Studia. Sa ovim se razdvojio dizaj i logika aplikacije te uvela nova tehnologija razvoja aplikacija kao i sistematičnija kolaboracija izmedju dizajnera i developera.

Informacije o WPF mogu se pronaći na internetu sa vrlo različitim novoima predznanja, te u ovom vrlo kratkom uvodu želio sam samo natuknuti neke od osnovnih značajki ove tehnologije. Svakako prije čitanja ovih postova potrebno je minimalno predznanje o WPF tehnologiji. Prvi post će biti prikazan u obliku tutorijala s kojim ćemo implementirati jednostavan primjer povezivanja baze podataka sa WPF aplikacijom, te upoznati osnovne operacije umetanja, modifikacije i brisanja zapisa iz baze podataka. Primjer će također prikazati neke od metoda na koji način koristimo Visual Studio 2008 i Microsoft Expression Blend u razvoju aplikcija. Za ovaj i primjere koji će biti prikazani u narednim postovima, potrebna je instalacija Visual Studio 2008 SP1, Expresion Blend 2, Microsoft SQL Server 2005 ili 2008,NorthWind baza podataka, a svi se oni mogu skinuti na microsoftovim stranicama, kao i u besplatin express verzijama.

NorthWind WPF primjer

Prije početka potrebno je NorthWind bazu podataka instalirati na server, kako bi se kroz Visual studio mogao formirati model baze podataka.

Pokrenimo VS 2008 te formirajmo novi WPF projekat kao na sljedećoj slici.

Nakon formiranja WPF projekta potrebno je formirati LINtoSQL model northwind baze podataka. Način na koji formiramo model možete pogledati na jednom od mojih prethodnih blog postova. Ovaj put naš model se sastoji od sljedećih tabela baze podataka: Customer, Employee, Order, Order_Detail. Sada naš projekat izgleda kao na slici 2.

U solucijskog exploreru možemo vidjeti da se naš projekat sastoji od Window1.xaml i korespodentne cs datoteke, App.xaml te korespodentne cs datoteke, kao i novoformiranog modela baze podataka kojeg smo objašnjavali u prethodnim postovima. Da bi NorthWind model baze podataka inkorporirali sa aplikacijom potrebno je dodatno implementirati logiku.

Kada sa prethodne slike desnim klikom miša odaberemo opciju View Code dobijamo implementaciju klase NorthWindKlaseDataContext. U klasi je potrebno implementirati metode za izvlačenje svih Narudžbi (Odrers), Dobavljača i Zaposlenika. Implementacija je prikazana u sljedećoj slici:

namespace NorthWindWPFPrimjer
{
    using System.Collections.ObjectModel;
    using System.Linq;

    partial class NorthWindKlaseDataContext
    {
        public ObservableCollection<Order> IzvuciNarudze()
        {
            var query = from p in Orders select p;
            return new ObservableCollection<Order>(query);
        }
        public ObservableCollection<Customer> IzvuciDobavljace()
        {
            var query = from p in this.Customers select p;
            return new ObservableCollection<Customer>(query);
        }
        public ObservableCollection<Employee> IzvuciZaposenike()
        {
            var query = from p in this.Employees select p;
            return new ObservableCollection<Employee>(query);
        }
    }
}

Važna napomena: Nemojte ni u kom slučaju using naredbe postavljati iznad prostora imena NorthWindWPFPrimjer jer će vam se izgubiti datoteka dizajnera i vaš model će nestati. Nažalost ovo je bug koji se nalazi u Visual Studio 2008 SP1.

Na ovaj način implementirali smo metode za izvlačenja podataka iz baze podataka. Sada je na redu da to implementiramo u window1.xaml datoteci. Da bi prikazali podatke o naružbama u window1.xaml datoteci potrebno je formirati objekat ObjectDataProvider kojim ćemo povezati kontrole za prikaz narudžbi. Naravno, ovaj tutorijal neće ulaziti u detalje i objašnjenja svih pojmova i tipova podataka, jer to i nije svrha. Možemo kazati da ObjectDataProvider obuhvata i formira objekat koji omogućuje povezivanje sa izvorom podataka. U WPF izvor podataka mogu biti klasični izvori podataka: vanjska baza podataka, XML datoteka, in memory kolekcija podataka, kao i svaka windowsova standardna ili kastomizirana kontrola, odnosno bilo koji .NET objekat. Ovo je i jedan od najvažnijih aspekata ove tehnologije. Kako smo na samom početku rekli XAML kao novi prograski jezik nije zamjena za klasične .NET jezike, on u biti predstavlja jedno proširenje .NET programskim jezicima, tako da sve što se može implementirati pomoću XAML-a možemo to učiniti i sa C# odnosno VB jezikom, dok obrnuto ne vrijedi.

Prilikom razvijanja aplikacije u WPF, implementacija u XAML datoteci označava deklarativnu implementaciju dok se implementacija u korespondentnom C# ili VB jeziku zove code-behind implementacija.

Dizaj aplikacije

Sada je potrebno našu aplikaciju dizajnirati, u principu potrebno je definisati kontrole koje će kasnije biti povezane sa bazom podataka odnosno sa tabelama i kolonama. Dizaj aplikacije sastoji se od jedne ListBox kontrole u kojoj će biti prikazane sve narudžbe, dok će sa desne strane biti polja u kojim će biti prikazani detalji svake narudžbe pojedinačno. Donja slika prikazuje dizaj prozora.

Sa desne strane postavili smo detalje svake narudžbe od kojih je najinteresantniji dio kolone Customer i Employee koji predstavljeju vanjske ključeve za tabele Customer i Employee. Preko ComboBoxa ostvarićemo ovu relaciju, gdje ćemo u combobox listi prikazati sve partnere (Customers) i zaposlenike (Employees). Obzirom da u standardnom setu kontrola ne postoji kontrola izbora Datuma i Vremena koristimo običnu edit kontrolu Text Box za prikaz datuma.

Cjelokupan dizajn gornjeg prozora uradili smo u XAML datoteci dok ćemo logiku aplikacije implementirati u cs datoteci ili tzv. Code-behind datoteci. Ovo je klasičan primjer upotrebe WPF tehnologije. Dizaj aplikacije implementirati u XAML, a logiku u code-behind datoteci.

Povezivanje sa bazom podataka

Da bi povezali aplikaciju sa bazom podataka potrebno je formirati objekat klase NorthWindKlaseDataContext preko kojeg ćemo vršiti upit prema bazi podataka. Ovdje ćemo pokazati dva načina implementacije. Jedan način je da u code-behind formiramo objekat te povežemo kontrole sa izvorom podataka, a drugi da u XAML-u uradimo isto. Oba načina su ispravna i nema nikave razlike u pogledu performansi. Na sljedećem ispisu prikazan je code-behind način. Listing datoteke Window1.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
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 NorthWindWPFPrimjer
{
    public partial class Window1 : Window
    {
        NorthWindKlaseDataContext dx = new NorthWindKlaseDataContext();
        public Window1()
        {
            InitializeComponent();

            listBox1.ItemsSource = dx.IzvuciNarudze();
            listBox1.DisplayMemberPath = "OrderID";

            Binding binding = new Binding();
            binding.Source = listBox1.ItemsSource;
             //OrderID
            binding.Path = new PropertyPath("OrderID");
            textBox1.SetBinding(TextBox.TextProperty, binding);

            //OrderID
            Binding binding1 = new Binding();
            binding1.Source = listBox1.ItemsSource;
            binding1.Path = new PropertyPath("CustomerID");
            comboBox1.ItemsSource = dx.IzvuciDobavljace();
            comboBox1.DisplayMemberPath = "ContactName";
            comboBox1.SelectedValuePath="CustomerID";
            comboBox1.SetBinding(ComboBox.SelectedValueProperty, binding1);

            //EmployeeID
            Binding binding2 = new Binding();
            binding2.Source = listBox1.ItemsSource;
            comboBox2.ItemsSource = dx.IzvuciZaposenike();
            comboBox2.DisplayMemberPath = "FirstName";
            comboBox2.SelectedValuePath = "EmployeeID";
            binding2.Path = new PropertyPath("EmployeeID");
            comboBox2.SetBinding(ComboBox.SelectedValueProperty, binding2);

            Binding binding3 = new Binding();
            binding3.Source = listBox1.ItemsSource;
            //OrderDate
            binding3.Path = new PropertyPath("OrderDate");
            textBox2.SetBinding(TextBox.TextProperty, binding3);

            Binding binding4 = new Binding();
            binding4.Source = listBox1.ItemsSource;
            //ShipVia
            binding4.Path = new PropertyPath("ShipVia");
            textBox3.SetBinding(TextBox.TextProperty, binding4);

            Binding binding5 = new Binding();
            binding5.Source = listBox1.ItemsSource;
            //Freight
            binding5.Path = new PropertyPath("Freight");
            textBox4.SetBinding(TextBox.TextProperty, binding5);

            Binding binding6 = new Binding();
            binding6.Source = listBox1.ItemsSource;
            //ShipPostalCode
            binding6.Path = new PropertyPath("ShipPostalCode");
            textBox5.SetBinding(TextBox.TextProperty, binding6);
        }
    }
}

Pokrenimo aplikaciju iz VS i dobićemo sljedeću sliku:

Ako pokušamo da selektujemo drugu stavku iz liste automatski cemo dobti druge vrijednosti u desnim kontrolama. Ovo automatsko sihroniziranje selektovane stavke iz liste i kontrola obezbjedjeno je formiranjem ObservableCollection klase te osobine liste IsSynchronizedWithCurrentItem=”True”.

Sljedeći listing prikazuje prethodno ali implementirano u XAML-u.

<Window x:Class="NorthWindWPFPrimjer.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:NorthWindWPFPrimjer"
    Title="NorthWind Prijmer" Height="357" Width="514" Closing="Window_Closing">
    <Window.Resources>
        <!--Formiranje ObjectDataProvidera preko NazivaMetode bez parametara-->
        <ObjectDataProvider x:Key="listaNarudzbi"
                            ObjectType="{x:Type local:NorthWindKlaseDataContext}" MethodName="IzvuciNarudzbe"/>
        <ObjectDataProvider x:Key="listaPartnera"
                            ObjectType="{x:Type local:NorthWindKlaseDataContext}" MethodName="IzvuciDobavljace"/>
        <ObjectDataProvider x:Key="listaZaposlenika"
                            ObjectType="{x:Type local:NorthWindKlaseDataContext}" MethodName="IzvuciZaposenike"/>
    </Window.Resources>
    <Grid>
        <!--Rešetka za raspored kontrola-->
        <Grid.RowDefinitions>
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="40" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="150" />
        </Grid.ColumnDefinitions>
        <!--List box kontrola za naslovom-->
        <TextBlock Margin="0,0,0,0" Name="textBlock1" Text="Lista Naružbi"
                   VerticalAlignment="Center" HorizontalAlignment="Center"
                   FontSize="16" FontWeight="Bold" Foreground="Chocolate" />
        <ListBox Name="listBox1" Grid.RowSpan="7" Grid.Row="1" IsSynchronizedWithCurrentItem="True"
                 ItemsSource="{Binding Source={StaticResource listaNarudzbi}}" DisplayMemberPath="OrderID" />

        <!--Labele za oznakama polja za editovanje-->
        <Label Grid.Column="1" Margin="10,12,0,0" Name="label1" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">OrderID:</Label>
        <Label Margin="6,6,4,6" Name="label2" Grid.Column="1" Grid.Row="1" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">Customer:</Label>
        <Label Margin="6,12,4,0" Name="label3" Grid.Column="1" Grid.Row="2" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">Employee:</Label>
        <Label Margin="6,6,4,6" Name="label4" Grid.Column="1" Grid.Row="3" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">Order Date:</Label>
        <Label Margin="6,6,4,6" Name="label5" Grid.Column="1" Grid.Row="4" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">Ship Via:</Label>
        <Label Margin="6,6,4,6" Name="label6" Grid.Column="1" Grid.Row="5" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">Freight:</Label>
        <Label Margin="6,12,4,0" Name="label7" Grid.Column="1" Grid.Row="6" HorizontalContentAlignment="Right"
               VerticalContentAlignment="Center">Postal Code:</Label>
        <!--Kontrole za modifikaciju i prikaz kolona narudžbe-->
        <TextBox Margin="0,8,0,8" Grid.Column="2" Grid.Row="0" Name="textBox1"
                 Text="{Binding Source={StaticResource listaNarudzbi}, Path=OrderID}" />
        <ComboBox Margin="0,8,0,8" Grid.Column="2" Grid.Row="1"  Name="comboBox1"
                  ItemsSource="{Binding Source={StaticResource listaPartnera}}"
                  SelectedValuePath="CustomerID"
                  SelectedValue="{Binding Source={StaticResource listaNarudzbi}, Path=CustomerID}"
                  DisplayMemberPath="ContactName"/>
        <ComboBox Margin="0,8,0,8" Name="comboBox2" Grid.Column="2" Grid.Row="2"
                  ItemsSource="{Binding Source={StaticResource listaZaposlenika}}"
                  SelectedValuePath="EmployeeID" SelectedValue="{Binding Source={StaticResource listaNarudzbi},  Path=EmployeeID}"
                  DisplayMemberPath="FirstName"/>
        <TextBox Margin="0,8,0,8" Name="textBox2" Grid.Column="2" Grid.Row="3"
                 Text="{Binding Source={StaticResource listaNarudzbi}, Path=OrderDate }" />
        <TextBox Margin="0,8,0,8" Name="textBox3" Grid.Column="2" Grid.Row="4"
                 Text="{Binding Source={StaticResource listaNarudzbi}, Path=ShipVia}" />
        <TextBox Margin="0,8,0,8" Name="textBox4" Grid.Column="2" Grid.Row="5"
                 Text="{Binding Source={StaticResource listaNarudzbi}, Path=Freight}" />
        <TextBox Margin="0,8,0,8" Name="textBox5" Grid.Column="2" Grid.Row="6"
                 Text="{Binding Source={StaticResource listaNarudzbi}, Path=ShipPostalCode}" />
        <!--Dugmad za brisanje i dodavanje stavki u bazu podataka-->
        <Button Grid.Column="2" Grid.Row="7" Margin="65,6,23,10" Name="button1">Obriši</Button>
        <Button Margin="21,6,17,10" Name="button2" Grid.Column="1" Grid.Row="7" Click="button2_Click">Nova</Button>
    </Grid>
</Window>

Podcrtani XAML kod označava novi kod koji smo dodali pri povezivanju kontrola sa bazom podataka.

Na samom početku definisali smo ObjectDataProvide preko NazivaMetode, i to za svaku tabelu. ObjectDataProvider uvijek se definiše unutar resursa Kontrole roditelja te na taj način objekt postaje vidljiv u svim kontrolama koje pripadaju datom roditelju.

Definisanje logike aplikacije

Prethodno smo definisali model baze podataka preko LINQtoSQL dizajnera, dodatno implementirali poslovnu logiku modela. Zatim smo dizajnirali našu aplikaciju na način da smo definisali raspored i vrste kontrola. Poslije toga povezali smo bazu podataka sa aplikacijom i prikazali podatke preko kontrola.

Za ovaj tutorijal ostaje da implementiramo CRUD operacije odnosno modifikaciju podataka, brisanje i dodavanje redova u bazu podataka. Za početak implementirajmo modifikaciju podataka na način da kad se aplikacija zatvori, da se provjeri da li su podaci mijenjani u odnosu na originalne podatke i baze podataka te na osnovu toga izvršiti modifikaciju baze podataka.

Za ovo nam je potrebno implementirati Closing dogadjaj.

Implementacija unosa novog reda u tabeli

Da bi uopće manipulisali prikazanim podacima u našoj aplikaciji potrebno je dobiti referencu na ListCollectionView a koja predstavlja tekuće podatke u našoj aplikaciji. Takodjer ako smo povezivanje uradili u XAML-u potrebno je definisati referencu na objekat NorthWindKlaseDataContext, a koju ćemo dobiti iz ObjectDataProvidera.

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
 {
  //U koliko je u toku zatvaranja prozora jos uvijek postojala modifikacija odredjene stavke
  //potrebo napraviti Refresh da bi sve promjene bile aktualizirane
  defaultView.Refresh();

  //Provjera da li postoji bilo kakva promjena koja bi se trebala zapisati u bazu podataka
  int br = dataContext.GetChangeSet().Deletes.Count +
           dataContext.GetChangeSet().Inserts.Count +
           dataContext.GetChangeSet().Updates.Count;

  if (br > 0)
    {
      if (MessageBox.Show("Da li želite pohraniti nastale promjene?",
           "WPF Primjer", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
        {
            dataContext.SubmitChanges();
        }
    }
 }

Iz tog razloga potrebno je na novou Windows objekta formirati članove na sljedeći način:

//Referenca na DefaultView koja je definisan u list kontroli
ListCollectionView defaultView;
//Referenca da DataContext
NorthWindKlaseDataContext dataContext;

Prilikom učitavanja aplikacije odnosno pozivanja dogadjaja Loaded potrebno je ove reference definisati:

private void Window_Loaded(object sender, RoutedEventArgs e)
 {
   //Referenca na DefaultView
   defaultView = (ListCollectionView)CollectionViewSource.GetDefaultView(listBox1.ItemsSource);
   dataContext = (NorthWindKlaseDataContext)(FindResource("listaNarudzbi") as ObjectDataProvider).ObjectInstance;

    Debug.Assert(defaultView != null);
    Debug.Assert(dataContext != null);
 }

Dodavanje nove stavke vrši se jednostavno na sljedeći način:

//Dodavanje nove stavke
private void button2_Click(object sender, RoutedEventArgs e)
 {
   //dodavanje nove stavke
   Order newOrder = (Order)defaultView.AddNew();
   //novoformiranu stavku pohraniti u bazu podataka prvi put kada se pozove SubmitCange
   dataContext.Orders.InsertOnSubmit(newOrder);

 }

Pozivom AddNew metode iz defaltView i novu stavku potrebno je registrovati u DataContext da bi se pohranile promjene. Kada pokrenemo aplikaciju i kliknemo da dugme Dodaj, u listBox na kraju se pojavi nova stavka. Sa desne strane popunimo polja. Prilikom zatvaranja aplikacija pojavljuje se upit za pohranu podataka.

Implementacija brisanja stavke

Birisanje stavke iz liste vršimo listingom prikazanim na sljedećoj slici:

//Brisanje tekuce stavke
private void button1_Click(object sender, RoutedEventArgs e)
  {
    if (MessageBox.Show("Da li želite obrisati tekuću stavku?",
         "WPF Primjer", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
          return;
    //Prvo je potrebno objekat da se objekat oznaci obrisan u DataContext
    dataContext.Orders.DeleteOnSubmit((Order)defaultView.CurrentItem);
    //Označeni objekat brisemo iz DafaulView
    defaultView.Remove(defaultView.CurrentItem);

  }

Pokrenemo aplikaciju te klikom na dugme Obriši pojavljuje se poruka za potvrdu brisanja stavke.

Zaključak

Ovim jednostavnim primjerom prikazali smo jedan od načina implementacije LINQ to SQL u WPF. Sljedećim postovima obradićemo manipulaciju sa podacima u smislu sortiranja grupiranja podataka. Također u narednim postovima govorićemo o konvertorima, kastomizaciji listbox kontrole i sl.

Izvorni kod za ovaj primjer možete skinuti sa ovog linka.