Kako podesiti pametne telefone i računare. Informativni portal
  • Dom
  • Windows 8
  • Konfiguriranje prikaza podataka sa povezivanjem podataka i WPF-om. Osnove WPF vezanja podataka

Konfiguriranje prikaza podataka sa povezivanjem podataka i WPF-om. Osnove WPF vezanja podataka

Napomena: Ovaj odjeljak pokriva osnovne koncepte povezivanja podataka u WPF-u. Brojni primjeri demonstriraju osnovne aspekte vezivanja elemenata interfejsa za vizuelne i nevizualne WPF objekte. Naprednije teme, kao što je vezivanje elemenata WPF interfejsa za prilagođene objekte i zbirke ukucanih podataka, ADO.NET framework objekti i predlošci, biće pokriveni kasnije.

dio I

Opće odredbe

Svi programi potrebni za obavljanje ovog posla nalaze se u priloženom katalogu.

Povezivanje podataka je mehanizam za izdvajanje informacija iz objekata u elemente interfejsa za prikaz i obrnuto - guranje informacija iz kontrola u objekte. Povezivanje podataka vam omogućava da radite malo ili nimalo kodiranja. Ovo je relativno stara tehnika, ali WPF dobila je dalji razvoj i ima svoje specifičnosti. Za svu složenost podržavanja povezivanja brinu bibliotečke klase i vrijeme izvođenja. Korice za uvezivanje širok raspon zadaci: od međusobnog povezivanja jednostavnih elemenata interfejsa do povezivanja baze podataka sa prilagođene forme interakcija sa podacima.

Uvezivanje podataka uvijek uključuje dvije strane: izvor i primaoca (ciljni element) informacija. Povezivanje podataka može pružiti jednosmjernu ili dvosmjernu komunikaciju povezanih svojstava objekta. Najčešće se koristi jednosmjerno povezivanje, čija je svrha izvlačenje informacija iz izvora i njihovo prikazivanje na prijemniku. Ali u nekim slučajevima, razlike između izvora i prijemnika se brišu, a ponekad se čak i njihove uloge obrnu - prijemnik počinje da dostavlja podatke izvoru.

Sintaksa povezivanja podataka, kao iu slučaju resursa, također ima dvije opcije: markup ekstenzije I elementi imovine, ali se razlikuje u detaljima. Ključni element Vezivanje za bilo koju opciju je definiranje Binding objekta iz imenskog prostora System.Windows.Data. Ovaj element je uvijek postavljen na strani primatelja vezivanja, osim u Mode=OneWayToSource . Prijemnik mora biti izveden iz klase DependencyObject, a svojstvo koje se može vezati (ciljno svojstvo) mora biti svojstvo zavisnosti. Ugrađena u svojstva zavisnosti je mogućnost slanja ili primanja obavještenja o promjenama.

Postoji mnogo manje zahtjeva za izvor vezivanja. Izvorno svojstvo koje se vezuje ne mora biti zavisno svojstvo. Glavna stvar je da izvor ima događaj upozorenja koji ukazuje na promjenu vezanog svojstva. Izvor povezivanja može biti bilo koje javno svojstvo, uključujući svojstva drugih kontrola, CLR objekata, XAML elemenata, ADO.NET skupova podataka, XML fragmenata itd. Da bi pravilno primijenio vezivanje na kompleksne objekte podataka, WPF pruža dvije specijalizirane klase, XmlDataProvider i ObjectDataProvider.

Također se nazivaju svojstva zavisnosti pripojen. U verziji XAML, namjenjeno za WPF, pripojena svojstva rade samo ako i tip u kojem je svojstvo definirano i tip na koji je pripojeno nasljeđuju klasu DependencyObject. Korištenje svojstava ovisnosti o jeziku XAML ima mogućnost proširenja tipova koristeći svojstva koja pružaju drugi tipovi. Kada se koristi u označavanju sintakse elementa svojstva, priloženom svojstvu uvijek prethodi ime tipa koji ga pruža, čak i ako se svojstvo koristi kao atribut.

Snap directions

Tip povezivanja elementa Binding određen je njegovim svojstvom Mode, koje može uzeti jednu od vrijednosti nabrajanja BindingMode iz imenskog prostora System.Windows.Data:

  • Default- je postavljeno prema zadanim postavkama i ovisi o tipu svojstva koje je vezano na strani primatelja (ciljno svojstvo). Djeluje kao dvosmjerni način povezivanja za svojstva u kojima je moguće uređivati korisnički interfejs, kao što je TextBox.Text ili CheckBox.Checked, ili kao jednosmjerno jednosmjerno povezivanje za druga svojstva. Da biste izbjegli oslanjanje na zadane postavke, trebali biste postaviti pravilo da uvijek eksplicitno postavite parametar smjera hvatanja.
  • Jednom- jednosmjerno početno povezivanje, kada se vrijednost ciljnog svojstva postavlja na vrijednost izvora samo jednom: tokom inicijalizacije, programska zamjena vezanog izvornog objekta novim, prilikom promjene svojstva DataContext ili kao rezultat programskog poziva metode BindingExpression.UpdateTarget(). Ostale dolazne obavijesti o promjenama na izvornoj strani primatelj neće uzeti u obzir
  • Jedan put- jednosmjerno vezivanje, gdje se ciljno svojstvo ažurira kada se promijeni izvorno svojstvo. Svaki put kada dođe do promjene na izvornoj strani, tok podataka se usmjerava od izvora do cilja.
  • OneWayToSource- organizira jednosmjerno povezivanje, kao OneWay, samo se izraz povezivanja stavlja u izvor. Ovaj trik može biti koristan kada odredišno svojstvo koje se vezuje nije svojstvo zavisnosti, ali izvorno svojstvo i dalje nasljeđuje klasu DependencyObject.
  • TwoWay- dvosmjerno vezivanje, gdje se ciljno svojstvo ažurira kada se promijeni izvorno svojstvo, a izvorno svojstvo se ažurira kada se promijeni ciljno svojstvo. Drugim riječima, dvosmjerni način povezivanja šalje podatke od izvora do cilja, a ako se vrijednost svojstva cilja promijeni, podaci se šalju natrag od cilja do izvora

Vježba 1: Vezivni element za element

U ovoj vježbi ćemo pogledati kreiranje komunikacijskog kanala između svojstava zavisnosti vizualnih elemenata WPF korisničkog sučelja koristeći niz primjera.

>

Povezivanje podataka u XAML-u

Dijeljenje objekata u XAML datoteci se također može obaviti putem povezivanja podataka. Zapravo uvezivanje podataka povezuje dva svojstva različitih objekata. Kao što ćemo kasnije pokazati, povezivanja podataka se najčešće koriste za povezivanje vizuala stranice sa izvorima podataka; osim toga, oni su važna komponenta implementacije popularnog arhitektonskog uzorka MVVM (Model-View-ViewModel). Vezivanja također igraju važnu ulogu u definiranju obrazaca prikaza objekata podataka.

Vezivanja podataka mogu se koristiti za povezivanje svojstava dva elementa. Vezivni element, kao i StaticResource, obično se izražava kao ekstenzija za označavanje, odnosno zatvorena u vitičaste zagrade. Međutim, Binding element također dozvoljava alternativni izraz u obliku sintakse elementa svojstva.

Koristite sljedeći rječnik resursa u našem testnom projektu:

Postavke četkice

Implicitni TextBlock stil ne sadrži svojstvo Foreground. LinearGradientBrush je definiran na prvom od četiri TextBlock elementa koji koriste tu četku, a sljedeći elementi TextBlock referiraju na isti kist kroz povezivanje:

Povezivanje podataka ima izvor I prijemnik (meta). Odredište je uvijek svojstvo na koje se postavlja vezivanje, a izvor je svojstvo za koje je vezano. Izvor prikazanih veza je TextBlock element pod nazivom topTxb; prijemnici su tri TextBlock elementa koji dijele svojstvo Foreground. Dva prijemnika predstavljaju standardniji način izražavanja Binding objekta kao XAML markup ekstenzije:

(Obvezujući ElementName=topTxb, Put=Prednji plan)

XAML oznake ekstenzije se uvijek stavljaju unutar vitičastih zagrada. U proširenju za označavanje za Binding, obično morate postaviti par svojstava, odvojenih zarezima. Svojstvo ElementName označava naziv elementa za koji je postavljeno željeno svojstvo; Svojstvo staze daje naziv svojstva.

Kada pišem ekstenzije za označavanje vezivanja, uvijek želim staviti vrijednosti svojstava u navodnike, ali to nije ispravno. U povezujućim izrazima nisu potrebni navodnici.

Posljednji element TextBlock demonstrira izraz Binding u manje uobičajenoj sintaksi elementa svojstva:

U ovoj sintaksi, navodnici oko vrijednosti svojstva su potrebni jer ovo su normalni XML atributi. Također možete kreirati Binding objekt u kodu i dodijeliti ga svojstvu primaoca koristeći metodu SetBinding() definisano u FrameworkElementu. Ovo otkriva da odredište vezivanja uvijek mora biti svojstvo zavisnosti.

Svojstvo Path klase Binding je tako nazvano jer može sadržavati više imena svojstava razdvojenih tačkama. Na primjer, pokušajte zamijeniti jednu od vrijednosti teksta u vašem projektu sa sljedećom vrijednošću:

Text="(Binding ElementName=topTxb, Path=FontFamily.Source)"

Prvi dio putanje označava da su nam potrebni podaci iz svojstva FontFamily. Svojstvo je postavljeno na objekt tipa FontFamily koji sadrži naziv Source, koji označava ime porodice fontova. Stoga će TextBlock prikazati tekst "Arial".

Pokušajte primijeniti sljedeću konstrukciju na bilo koji element TextBlock u našem projektu:

Text="(Obvezujući RelativeSource=(RelativeSource Self), Path=FontSize)"

Evo proširenja za označavanje RelativeSource nalazi se unutar ekstenzije oznake za vezivanje i koristi se za referencu na svojstvo elementa za koji se postavlja povezivanje.

  • Programiranje
  • Jedna od ključnih tačaka razvoja xaml-orijentisane aplikacije je da koriste veze ( Vezi). Uvezivanje- Ovo posrednik(posrednik), uz pomoć kojeg se sinkroniziraju vrijednosti svojstava između povezanih objekata.

    Vrijedi napomenuti ne očiglednu, ali važnu nijansu: Iako se vezivanje na neki način poziva na objekte koji su u interakciji, to ih ne sprečava da se skupljaju smeće!

    Nasljeđe iz klase Uvezivanje dozvoljeno, ali iz sigurnosnih razloga koda koji nadjačavaju metodu ProvideValue, koji se odnosi na glavnu operativnu logiku, nije dozvoljeno. Ovo nekako provocira programere da koriste obrazac Converter, koji je usko isprepleten sa temom poveza.

    Vezivanja su vrlo moćan alat, ali u nekim slučajevima njihova deklaracija postaje opširna i nezgodna za redovnu upotrebu, na primjer, za lokalizaciju. U ovom članku ćemo pogledati jednostavnu i elegantnu metodu koja čini kod mnogo čišćim i ljepšim.


    Objavite veze u xaml dozvoljeno na dva načina:



    Očigledno, prva metoda ne izgleda baš sažeto, ali druga, zasnovana na upotrebi markup ekstenzije, najčešće se koristi. Na platformi WPF postoji prilika za stvaranje prilagođene ekstenzije oznake. Na primjer, pogodni su za korištenje za lokalizaciju.


    U najjednostavnijem slučaju, morate naslijediti od klase MarkupExtension i implementirati metodu ProvideValue, u kojem se pomoću ključa dobija željena vrijednost.

    Ali ova implementacija ne podržava vruća smjena jezik tokom izvršavanja programa. Da bi se ovo poboljšalo, potrebno je, prvo, pohraniti referencu na lokalizirani element sučelja, i drugo, što je manje očito, na neki način u aplikaciji imati referencu na samu instancu klase Lokaliziranje, da se zaštiti od sakupljanja smeća, i treće, potrebno je pravilno implementirati pretplatu i odjavu od događaja promjene jezika.

    Ako ove stvari učinite pogrešno, zajamčeno vam je curenje memorije ako se pogledi kreiraju i uništavaju dinamički dok aplikacija radi, što je slučaj u mnogim slučajevima. Odnosno, dodavanjem naizgled ne najsloženije funkcije, morat ćete se baviti netrivijalnim temama slabe karike I slabe pretplate na događaje. A kod neće biti baš jednostavan.

    Štaviše, na xaml-platforme Windows Phone , Windows prodavnica I Xamarin.Forms ne postoji način za kreiranje prilagođenih ekstenzija za označavanje, što donosi ideju korištenja povezivanja kao ekstenzija za označavanje

    Hajde da ne lupamo okolo, evo šta nam treba:

    Javna apstraktna klasa BindingExtension: Binding, IValueConverter ( protected BindingExtension() ( Source = Converter = this; ) protected BindingExtension(object source) // postavite Source na null za korištenje DataContext ( Source = source; Converter = this; ) zaštićen BindingExtension(RelativeSour) relativeSource) ( RelativeSource =relativeSource; Converter = this; ) javni apstraktni objekat Convert(vrijednost objekta, Type targetType, parametar objekta, kultura CultureInfo); javni virtualni objekat ConvertBack(vrijednost objekta, Type targetType, parametar objekta, kultura CultureInfo) (baci novi NotImplementedException(); ) )
    Važno je napomenuti da je uvez samo za sebe pretvarač. Kao rezultat, dobijamo ponašanje vrlo slično onom nasljeđivanja od klase MarkupExtension, ali, pored toga, Ostaje moguće koristiti standardne mehanizme kontrole sakupljanja smeća!

    Sada logika izgleda lokalizacije ne može biti jednostavnija:

    Javna djelomična klasa Localizing: Base.BindingExtension ( javni statički menadžer samo za čitanje ActiveManager = novi upravitelj(); public Localizing() ( Izvor = ActiveManager; Put = novi PropertyPath("Source"); ) javno lokaliziranje (niz ključ) ( Ključ = ključ ; Source = ActiveManager; Put = new PropertyPath("Source"); ) javni string Key ( get; set; ) javni nadjačavajući objekt Convert (vrijednost objekta, Type targetType, parametar objekta, CultureInfo kultura) ( var ključ = Ključ; var resourceManager = vrijednost kao ResourceManager; var localizedValue = resourceManager == null || string.IsNullOrEmpty(key) ? ":" + ključ + ":" : (resourceManager.GetString(key) ?? ":" + ključ + ":") ; vrati localizedValue; ) )
    javna djelomična klasa Localizing ( javna klasa Manager: INotifyPropertyChanged ( privatni ResourceManager _source; javni izvor ResourceManager ( get ( return _source; ) set ( _source = vrijednost; PropertyChanged(ovo, novi PropertyChangedEventArgs("Source")); ) ) javni string Get( string ključ, string stringFormat = null) ( if (_source == null || string.IsNullOrWhiteSpace(key)) povratni ključ; var localizedValue = _source.GetString(key) ?? ":" + ključ + ":"; vrati string .IsNullOrEmpty(stringFormat) ? localizedValue: string.Format(stringFormat, localizedValue); ) javni događaj PropertyChangedEventHandler PropertyChanged = (pošiljalac, args) => ( ); ) )
    Lako je dodati mogućnost promjene velikih i malih slova:

    Javna parcijalna klasa Localizing: Base.BindingExtension ( javni enum Cases ( Default, Lower, Upper ) javni statički samo za čitanje Manager ActiveManager = new Manager(); public Localizing() ( Source = ActiveManager; Put = new PropertyPath("Source"); ) public Localizing(string key) (Ključ = ključ; Izvor = ActiveManager; Putanja = novi PropertyPath("Source"); ) javni string Key (dobiti; set; ) javni slučajevi Slučaj (dobiti; set;) javni nadjačati string ToString() ( vrati Convert(ActiveManager.Source, null, Key, Thread.CurrentThread.CurrentCulture) kao string ?? string.Empty; ) javni nadjačavanje objekta Convert(vrijednost objekta, Tip targetType, parametar objekta, kultura CultureInfo) ( var ključ = Ključ; var resourceManager = vrijednost kao ResourceManager; var localizedValue = resourceManager == null || string.IsNullOrEmpty(key) ? ":" + ključ + ":" : (resourceManager.GetString(key) ?? ":" + ključ + ": "); prekidač (Case) ( case Cases.Lower: povratak localizedValue.ToLower(); case Cases.Upper: povratak localizedValue.ToUpper(); default: return localizedValue; ) ) )
    IN xaml Snimak izgleda zgodno i lijepo, ali postoje neka ograničenja markup parsera na raznim platformama:


    Riješiti se WPF od traženog prefiksa m: morate postaviti proširenje za označavanje u poseban sklop i u Properties/AssemblyInfo.cs navedite sljedeće direktive:


    Da biste prilagodili naziv prefiksa Windows Phone ili Store:


    Korištenje ekstenzija za vezivanje ( Binding Extensions) uključeno WPF ne isključuje redovna proširenja za označavanje, ali je u nekim slučajevima čak i sigurnija i jednostavna opcija. Također, sve ovo nije ograničeno samo na lokalizaciju, već je pogodno za mnoge druge svrhe...

    Demonstrirani pristup se uveliko koristi u biblioteci

    Kada Windows platforma Presentation Foundation (WPF) se prvi put pojavio na .NET radaru, sa većinom članaka i demonstracija koji hvale njen vrhunski mehanizam za renderovanje i mogućnosti renderovanja. 3D grafika. Iako ih je zabavno čitati i igrati se, takvi primjeri ne odražavaju šire stvarne prilike WPF. Većina nas ne treba da kreira aplikacije sa rotirajućim video kockama koje eksplodiraju u vatromet kada se kliknu. Većina nas živi stvarajući softver za prikaz i uređivanje velikih količina složenih naučnih ili poslovnih podataka.

    Dobra vijest je da WPF nudi odličnu podršku za upravljanje prikazom i uređivanje složenih podataka. U izdanju MSDN® Magazina iz decembra 2007., John Papa je napisao članak, “Vezivanje podataka u WPF-u” (msdn.microsoft.com/magazine/cc163299), koji odlično objašnjava ključne koncepte povezivanja podataka u WPF-u. Ovdje ću se osvrnuti na složenije slučajeve vezivanja podataka, nadovezujući se na ono što je John predstavio u gore spomenutoj seriji Data Points. Nakon čitanja, čitaoci će biti svjesni različitih načina implementacije uobičajenih zahtjeva vezanih za podatke koji se mogu vidjeti u većini poslovnih aplikacija.

    Vezivanje u kodu

    Jedna od najvećih promjena koje WPF uvodi programerima desktop aplikacija je njegova široka upotreba i podrška deklarativnom programiranju. WPF korisnički interfejsi i resursi mogu se deklarisati korišćenjem Extensible Application Markup Language (XAML), standardnog jezika za označavanje zasnovanog na XML-u. Većina objašnjenja WPF povezivanja podataka samo pokazuje kako se radi sa vezama u XAML-u. Pošto se sve što se može uraditi u XAML-u može postići i u kodu, važno je da profesionalni WPF programeri znaju da rade sa povezivanjem podataka ne samo deklarativno, već i programski.

    U mnogim slučajevima, lakše je i praktičnije deklarisati vezivanja u XAML-u. Kako sistemi postaju složeniji i dinamičniji, ponekad ima smisla raditi sa vezama u kodu. Prije nego što krenemo dalje, pogledajmo neke uobičajene klase i metode uključene u programsko povezivanje podataka.

    WPF elementi nasljeđuju metode SetBinding i GetBindingExpression iz FrameworkElementa ili FrameworkContentElementa. Ovo su jednostavno praktične metode koje pozivaju metode s istim imenima u uslužnoj klasi BindingOperations. Kod ispod pokazuje kako koristiti klasu BindingOperations za povezivanje Svojstva teksta tekstualni okvir do svojstva na drugom objektu:

    Statički void BindText(TextBox textBox, svojstvo stringa)
    {
    if (!BindingOperations.IsDataBound(textBox, textProp))
    {
    Vezivanje b = novo Vezivanje(svojstvo);
    BindingOperations.SetBinding(textBox, textProp, b);
    }
    }

    Lako je odvezati svojstvo koristeći sljedeći kod:

    Statička praznina UnbindText(TextBox textBox)
    {
    DependencyProperty textProp = TextBox.TextProperty;
    if (BindingOperations.IsDataBound(textBox, textProp))
    {
    BindingOperations.ClearBinding(textBox, textProp);
    }
    }

    Prilikom brisanja povezivanja, vezana vrijednost se također uklanja iz ciljnog svojstva.

    Deklarisanje vezivanja podataka u XAML-u skriva neke osnovne detalje. Kada počnete da radite sa vezama u kodu, ovi detalji počinju da isplivavaju na površinu. Jedan je da odnos između izvora vezivanja i njegovog cilja zapravo održava instanca klase BindingExpression, a ne sama klasa Binding. Klasa Binding sadrži informacije visokog nivoa koje mogu da dele više klasa BindingExpression, ali osnovni izraz obezbeđuje vezu između dva vezana svojstva. Sljedeći kod pokazuje kako se BindingExpression može koristiti da se programski osigura da je svojstvo Text okvira za tekst označeno:

    static bool IsTextValidated(TextBox textBox)
    {
    DependencyProperty textProp = TextBox.TextProperty;

    var expr = textBox.GetBindingExpression(textProp);
    if (expr == null)
    return false;

    Vezivanje b = expr.ParentBinding;
    return b.ValidationRules.Any();
    }

    Pošto klasa BindingExpression ne zna da se provjerava valjanost, mora se postaviti pitanje o njenom roditeljskom povezivanju. U nastavku ću raspravljati o različitim tehnikama validacije unosa.

    Rad sa predlošcima

    Efikasno korisničko sučelje predstavlja sirove podatke na način koji omogućava korisniku da intuitivno izvuče značajne informacije iz njih. Ovo je suština vizualizacije podataka. Povezivanje podataka je samo jedan dio slagalice za vizualizaciju podataka. Svi osim najtrivijalnijih WPF programa zahtijevaju način predstavljanja podataka koji je moćniji od jednostavnog vezivanja jednog svojstva na kontroli za jedno svojstvo na objektu podataka. Pravi objekti podataka imaju mnoga svojstva koja se odnose na njih, a ta različita svojstva moraju konvergirati u kohezivni vizualni prikaz. To je razlog zašto WPF ima predloške podataka.

    Klasa System.Windows.DataTemplate je samo jedan oblik predloška u WPF-u. U osnovi, predložak je rezač kolačića koji WPF okvir koristi za kreiranje vizualnih elemenata koji pomažu u prikazivanju objekata koji nemaju vlastiti vizualni prikaz. Kada element pokuša da prikaže objekat koji nema takvu reprezentaciju, recimo nestandardni poslovni objekat, možete reći elementu kako da prikaže objekat tako što ćete mu dati DataTemplate.
    DataTemplate može kreirati onoliko vizuala koliko je potrebno za prikaz objekta podataka. Ovi elementi koriste povezivanja podataka za prikaz vrijednosti svojstava objekta podataka. Ako element ne zna kako da prikaže objekat koji mu je rečeno da renderuje, on jednostavno poziva metodu ToString na njemu i prikazuje rezultate u TextBlock-u.

    Recimo da imamo jednostavnu klasu pod nazivom FullName koja pohranjuje ime osobe. Želite da prikažete listu imena po kojoj se prezime svake osobe izdvaja od ostalih. Da biste to učinili, možete kreirati DataTemplate koji opisuje kako prikazati objekt FullName. Kod prikazan na sl. 1, prikazuje klasu FullName i pozadinski kod za prozor koji će prikazati listu imena.

    Rice. 1. Prikaz FullName objekata koristeći DataTemplate

    javna klasa Puno ime
    {
    javni string Ime (dobi; postavi;)
    javni znak MiddleInitial (dobi; postavi;)
    javni string Prezime (dobi; postavi;)
    }

    javna parcijalna klasa WorkingWithTemplates: Window
    {
    // Ovo je konstruktor prozora.
    public WorkingWithTemplate()
    {
    InitializeComponent();

    base.DataContext = novo puno ime
    {
    novo puno ime
    {
    Ime = "Johann",
    MiddleInitial = "S",
    Prezime = "Bach"
    },
    novo puno ime
    {
    Ime = "Gustav",
    MiddleInitial = " ",
    Prezime = "Mahler"
    },
    novo puno ime
    {
    Ime = "Alfred",
    MiddleInitial = "G",
    Prezime = "Schnittke"
    }
    };
    }
    }

    Kao što se može videti na sl. 2, Postoji kontrola ItemsControl u XAML datoteci prozora. Kreira jednostavnu listu stavki koje korisnik ne može odabrati ili izbrisati. ItemsControl ima DataTemplate dodijeljen njegovom svojstvu ItemTemplate, s kojim prikazuje svaku instancu FullName kreiranu u konstruktoru prozora. Primijetit ćete da većina TextBlock elemenata u DataTemplateu ima svojstvo Text vezano za svojstva objekta FullName koji predstavljaju.

    Rice. 2. Prikaz FullName objekata koristeći DataTemplate














    Kada pokrenete ovu demo aplikaciju, ona izgleda kao na sl. 3. Korišćenje DataTemplate-a za renderovanje imena olakšava isticanje prezimena svake osobe jer je postavka FontWeight odgovarajućeg TextBlock-a podebljana. Ovaj jednostavan primjer pokazuje odnos između WPF povezivanja podataka i predložaka. Kako dublje ulazim u temu, kombinirat ću ove funkcije kako bih stvorio načine za vizualizaciju složeni objekti sa sve većim mogućnostima.

    Rice. 3. Objekti punog imena koje prikazuje DataTemplate

    Rad sa naslijeđenim kontekstom podataka

    Osim ako nije drugačije navedeno, sva povezivanja se implicitno vežu za svojstvo DataContext elementa. DataContext elementa se odnosi na njegov izvor podataka, da tako kažemo. Postoji nekoliko posebnih stvari koje trebate znati o tome kako DataContext funkcionira. Razumijevanje ovog implicitnog aspekta DataContext-a čini mnogo lakšim dizajniranje složenih korisničkih sučelja vezanih za podatke.

    Za upućivanje na objekt izvora podataka nije potrebno postaviti svojstvo DataContext. Ako je svojstvu DataContext elementa pretka u stablu elementa (tehnički rečeno, logičko stablo) data vrijednost za njegov DataContext, tada će vrijednost automatski biti naslijeđena od strane svakog izvedenog elementa u korisničkom sučelju. Drugim riječima, ako je DataContext postavljen da se odnosi na Foo objekt, tada će se, prema zadanim postavkama, DataContext svakog elementa u prozoru odnositi na isti Foo objekt. Bilo kojem elementu u prozoru može se lako dati vlastita vrijednost DataContext, što će uzrokovati da svi elementi koji proizlaze iz tog elementa naslijede novu vrijednost DataContext. Ovo je slično eksternom svojstvu u Windows Forms.

    U prethodnom odjeljku, pogledao sam korištenje DataTemplatea za kreiranje vizualizacija objekata podataka. Svojstva elemenata kreiranih šablonom na Sl. 2 su vezani za svojstva objekta FullName. Ovi elementi su implicitno vezani za svoj DataContext. Svojstvo DataContext elemenata kreiranih predloškom DataTemplate odnosi se na objekt podataka za koji se predložak koristi, kao što je objekt FullName.

    Nema magije u nasljeđivanju vrijednosti svojstva DataContext. Ovo jednostavno koristi ugrađenu podršku WPF-a za naslijeđena svojstva zavisnosti. Bilo koje svojstvo zavisnosti može biti naslijeđeno svojstvo ako mu se jednostavno dodijeli oznaka u metapodacima datim prilikom registracije tog svojstva u WPF sistemu svojstava zavisnosti.

    Drugi primjer naslijeđenog svojstva zavisnosti je da svi elementi imaju Svojstvo veličine fonta. Ako postavite svojstvo zavisnosti FontSize na prozor, tada će po defaultu svi elementi u ovom prozoru biti prikazani kao tekst u veličini fonta koju je on odredio. Infrastruktura koja se koristi za propagiranje vrijednosti FontSize niz stablo elemenata također propagira DataContext.

    Ovdje se termin "nasljeđivanje" koristi u značenju različitom od njegovog objektno orijentiranog smisla, gdje potklasa nasljeđuje članove roditeljske klase. Nasljeđivanje vrijednosti svojstava odnosi se samo na propagaciju vrijednosti niz stablo elemenata u vrijeme izvođenja. Naravno, klasa može naslijediti svojstvo zavisnosti da podrži nasljeđivanje vrijednosti u objektno orijentiranom smislu.

    Rad sa prikazima kolekcije

    Kada se WPF kontrole vežu za kolekciju podataka, one se ne vezuju direktno za samu kolekciju. Umjesto toga, oni se implicitno vezuju za pogled, koji automatski postaje omotač te kolekcije. Pogled implementira ICollectionViews interfejs i može biti jedna od nekoliko konkretnih implementacija, kao što je ListCollectionView.

    Predstavljanje kolekcije ima nekoliko zadataka. Prati trenutnu stavku u kolekciji, koja je obično odabrana/aktivna stavka u kontroli okvira sa listom. Prikazi zbirke također nude općenite načine naručivanja, filtriranja i grupiranja stavki na listi. Više kontrola se može vezati za isti prikaz oko kolekcije, osiguravajući njihovu međusobnu koordinaciju. Kod ispod pokazuje neke od mogućnosti ICollectionViewa:

    // Dobivamo zadani prikaz omotan oko liste kupaca.
    ICollectionView pogled = CollectionViewSource.GetDefaultView(allCustomers);

    // Odabrati kupca u korisničkom sučelju.
    Customer selectedCustomer = view.CurrentItem kao Kupac;

    // Postavite odabranog kupca u korisničkom sučelju.
    view.MoveCurrentTo(someOtherCustomer);

    Sve kontrole tipa liste, uključujući okvire liste, kombinovane okvire i prikaze liste, moraju imati svojstvo IsSynchronizedWithCurrentItem postavljeno na true da bi ostale sinhronizovane sa svojstvom prikaza kolekcije CurrentItem. Ovo svojstvo definira apstraktnu klasu Selector. Ako nije postavljeno na true, tada odabir stavke u kontroli okvira s listom neće ažurirati CurrentItem prikaza kolekcije, a postavljanje CurrentItem na novu vrijednost neće se odraziti na kontrolu okvira s listom.

    Rad sa hijerarhijskim podacima

    Stvarni svijet je pun hijerarhijskih podataka. Kupac daje nekoliko narudžbi, molekul se sastoji od mnogo atoma, odeljenje se sastoji od mnogo zaposlenih, a Sunčev sistem sadrži grupu nebeskih tela. Čitaoci su bez sumnje upoznati sa ovom shemom master/detail.
    WPF pruža različite načine rada sa hijerarhijskim strukturama podataka, od kojih je svaki pogodan za različite situacije. U suštini, alternativa je ili korištenje više kontrola za prikaz podataka ili prikaz više razina hijerarhije podataka u jednoj kontroli. Ovdje ću analizirati oba ova pristupa.

    Upotreba više kontrola za prikaz XML podataka

    Vrlo uobičajen način rada sa hijerarhijskim podacima je da se svaki nivo hijerarhije prikaže kao posebna kontrola. Kao primjer, recimo da imamo sistem koji predstavlja kupce, porudžbine i detalje porudžbine. U takvoj situaciji, kombinirani okvir se može koristiti za prikaz kupaca, okvir s popisom za prikaz svih narudžbi odabranih kupaca i na kraju ItemsControl za prikaz detalja odabrane narudžbe. Ovo odličan način prikazivanje hijerarhijskih podataka i njihovo implementiranje u WPF je prilično jednostavno.

    Na sl. Slika 4, zasnovana na gore opisanoj situaciji, prikazuje pojednostavljeni primjer podataka sa kojima aplikacija može raditi, umotanih u komponentu WPF XmlDataProvider. Ovi podaci se mogu prikazati u korisničkom interfejsu sličnom onom prikazanom na Sl. 5. Imajte na umu da se kupci i narudžbe mogu birati, ali detalji narudžbe postoje u obrascu liste samo za čitanje. Postoji razlog za to - mogućnost odabira vizualnog objekta treba dati samo kada utiče na stanje aplikacije ili je promjenjiv.

    Rice. 4. Hijerarhija narudžbi kupaca i informacije o narudžbi u XML formatu





















    Rice. 5 Jedan od načina za prikaz XML podataka

    U XAML kodu na sl. 6 opisuje kako ih koristiti razni elementi kontrole za prikaz upravo prikazanih hijerarhijskih podataka. Ovaj prozor ne zahtijeva kod; u potpunosti postoji u XAML kodu.

    Rice. 6. XAML kod za vezivanje hijerarhijskih XML podataka na korisničko sučelje

    "(Izvor vezivanja=(StaticResource xmlData),
    XPath=kupci/kupac)"
    Margin="4"
    >







    ItemsSource="(Uvezivanje)"
    >









    x:Name="orderSelector"
    DataContext="(Putanja vezivanja=Trenutna stavka)"
    IsSynchronizedWithCurrentItem="Tačno"
    ItemsSource="(Binding XPath=red)"
    >








    Text="Detalji narudžbe" />
    DataContext=
    "(Obvezujući ElementName=orderSelector, Path=SelectedItem)"
    ItemsSource="(Binding XPath=orderDetail)">



    proizvod:

    (

    )





    Obratite pažnju na ekstenzivnu upotrebu kratkih XPath upita za upućivanje WPF-a na to gdje da dohvati vezane vrijednosti. Klasa Binding pruža svojstvo XPath koje se može dodijeliti bilo kojem XPath upitu podržanom metodom XmlNode.SelectNodes. WPF interni elementi koriste ovu metodu za izvršavanje XPath upita. Nažalost, to znači da pošto XmlNode.SelectNodes trenutno ne podržava upotrebu XPath funkcija, WPF povezivanje podataka ih ne podržava.

    Kutija s popisom kupaca i lista narudžbi vezani su za rezultirajući skup XPath čvorova upita koje izvršava upit DataContext korijenskog elementa Grid. DataContext liste će automatski vratiti CurrentItem pogleda kolekcije, koji je omotač za kolekciju XmlNodes kreiranu za DataContext tabele. Drugim riječima, DataContext liste je onaj u kojem je odabran trenutno klijent. Zato što je ItemsSource liste implicitno vezan za vlastiti DataContext (jer nije naveden nijedan drugi izvor) i njegovo ItemsSource povezivanje izvodi XPath upit za dohvat stavki iz DataContext, onda je ItemsSource zapravo vezan za listu narudžbi odabranog kupca.

    Zapamtite da kada se povezujete sa XML podacima, stvarno vezivanje je za objekte kreirane pozivom na XmlNode.SelectNodes. Ako niste pažljivi, možete završiti s više kontrola koje se vežu za logički ekvivalentne, ali fizički razni setovi XmlNodes. To je zato što svaki poziv XmlNode.SelectNodes kreira novi skup XmlNodes, čak i ako proslijedite isti XPath upit na isti XmlNode svaki put. Ovo je poseban problem sa vezivanjem za XML podatke, tako da ga možete bezbedno zanemariti kada se povezujete sa poslovnim objektima.

    Upotreba više kontrola za prikaz poslovnih objekata

    Sada recimo da želite da se povežete sa podacima iz prethodnog primera, ali podaci postoje kao poslovni objekti, a ne u XML kodu. Kako će to promijeniti način na koji se vezujemo za različite nivoe hijerarhije podataka? Koliko će prijem biti sličan ili različit?

    U kodu na sl. Slika 7 prikazuje jednostavne klase koje se koriste za kreiranje poslovnih objekata koji pohranjuju podatke na koje će biti vezani. Ove klase čine iste logičko kolo, isto kao i XML podaci korišteni u prethodnom odjeljku.

    Rice. 7. Klase za kreiranje hijerarhije poslovnih objekata

    kupac javne klase
    {
    javni string Ime ( get; set; )
    javna lista Narudžbe (dobi; postavi;)


    {
    return this.Name;
    }
    }

    javna klasa Red
    {
    javni niz Desc (dobi; postavi;)
    javna lista Detalji narudžbe (dobiti; postaviti;)

    javno nadjačavanje niza ToString()
    {
    return this.Desc;
    }
    }

    javna klasa OrderDetail
    {
    javni niz Proizvod (dobi; postavi;)
    public int Količina (dobi; postavi;)
    }

    XAML kod za prozor koji prikazuje ove objekte prikazan je na Sl. 8. Veoma je sličan XAML kodu na sl. 6, ali ima između bitne razlike, na koje vrijedi obratiti pažnju. Ono što XAML kod ne vidi je konstruktor prozora koji kreira objekte podataka i postavlja DataContext, a ne XAML kod koji postavlja referencu na njega kao na resurs. Imajte na umu da nijedna kontrola nema svojstvo DataContext direktno postavljeno. Svi oni nasljeđuju isto svojstvo DataContext, a to je instanca liste .

    Rice. 8. XAML kod za vezivanje hijerarhijskih poslovnih objekata na korisničko sučelje








    />
    IsSynchronizedWithCurrentItem="Tačno"
    ItemsSource="(Binding Path=.)"
    />




    IsSynchronizedWithCurrentItem="Tačno"
    ItemsSource="(Obvezujuća staza=Trenutna stavka.Narudžbe)"
    />



    Text="Detalji narudžbe" />
    ItemsSource="(Binding Path=CurrentItem.Orders.CurrentItem.
    Detalji narudžbe)"
    >



    proizvod:

    (

    )





    Još jedna značajna razlika kod vezivanja za poslovne objekte umjesto XML-a je da ItemsControl koji drži informacije o narudžbi ne mora da se veže za SelectedItem na listi narudžbi. Ovaj pristup je bio neophodan u slučaju XML vezivanja zbog nedostatka univerzalna metoda odnose se na trenutni element liste čiji elementi dolaze iz lokalnog XPath upita.

    Prilikom vezivanja za poslovne objekte umjesto XML-a, vezivanje za ugniježđene razine odabranih elemenata je trivijalan zadatak. ItemsControl-ov ItemsSource vezivanje koristi ovo zgodna funkcija, navodeći CurrentItem dvaput na putu vezivanja: jednom za odabranog kupca, jednom za odabranu narudžbu. Svojstvo CurrentItem je član osnovnog ICollectionViewa, koji obavija izvor podataka, kao što je gore objašnjeno.

    Postoji još jedna zanimljiva stvar koja se odnosi na razliku u načinu rada XML-a i poslovnog objekta. Budući da se XML primjer veže za XmlElements, morate obezbijediti DataTemplate da biste objasnili kako vizualizirati kupce i narudžbe. Kada se povezujete sa prilagođenim poslovnim objektima, možete izbjeći ovaj dodatni posao jednostavnim nadjačavanjem metode ToString klasa Customer i Order i dopuštanjem WPF-u da prikaže izlaz te metode za te objekte. Ovaj trik je dovoljan samo za objekte koji mogu imati jednostavne tekstualne reprezentacije. Kada radite sa složeni objekti podataka, korištenje ove zgodne tehnike možda neće imati smisla.

    Jedna kontrola za prikaz cijele hijerarhije

    Prije u ovom momentu Pokazao je samo načine za prikazivanje hijerarhijskih podataka prikazivanjem svakog nivoa hijerarhije u zasebnim kontrolama. Često je korisno i neophodno demonstrirati sve nivoe hijerarhijske strukture podataka u jednoj kontroli. Kanonski primjer ovog pristupa je kontrola TreeView, koja podržava prikaz i ponavljanje kroz proizvoljan broj nivoa ugniježđenih podataka.

    Možete popuniti TreeView u WPF elementima na jedan od dva načina. Prvi način je da se elementi dodaju ručno u kodu ili u XAML-u, a drugi je da ih kreirate putem povezivanja podataka.

    Sljedeći XAML pokazuje kako možete dodati TreeViewItems u TreeView u XAML-u:







    Tehnika ručnog kreiranja elemenata u TreeViewu ima smisla u situacijama u kojima će kontrola uvijek prikazati mali i statičan skup elemenata. Kada postoji potreba za prikazom velikih količina podataka koji se mogu promijeniti tokom vremena, postaje neophodan dinamičniji pristup. U ovoj fazi postoje dvije opcije. Možete napisati kod koji prelazi strukturu podataka, kreira TreeViewItems na osnovu objekata podataka koje pronađe i dodaje te stavke u TreeView. Alternativa je da koristite hijerarhijske šablone podataka i prepustite sav posao WPF-u.

    Korištenje hijerarhijskih predložaka podataka

    Kako bi WPF trebao vizualizirati hijerarhijske podatke kroz hijerarhijske predloške podataka može se izraziti deklarativno. Klasa HierarchicalDataTemplate je alat koji premošćuje jaz između složene strukture podataka i vizualnog prikaza tih podataka. Vrlo je sličan normalnom DataTemplateu, ali vam također omogućava da odredite odakle dolaze djeca objekta podataka. Takođe možete dati klasi HierarchicalDataTemplate sa šablonom za prikazivanje ove djece.

    Pretpostavimo da sada želimo prikazati podatke prikazane na Sl. 7 unutar jedne TreeView kontrole. Rezultirajući TreeView može izgledati nešto poput onog prikazanog na Sl. 9. Implementacija ovoga uključuje korištenje dva HierarchicalDataTemplatea i jednog DataTemplatea.

    Rice. 9. Prikaz cijele hijerarhije podataka u prikazu stabla

    Dva hijerarhijska predloška prikazuju objekte Customer i Order. Budući da objekti OrderDetail nemaju djece, mogu se prikazati pomoću nehijerarhijskog DataTemplatea. Svojstvo ItemTemplate TreeView-a koristi predložak za objekte Customer jer su objekti Customer i objekti podataka sadržani na osnovnom nivou TreeView-a. U XAML kodu prikazanom na sl. Slika 10 pokazuje kako se svi dijelovi ove slagalice spajaju.

    Rice. 10. XAML iza TreeView-a




    xmlns:local="clr-namespace:VariousBindingExamples"
    ObjectType="(x:Type local:Customer)"
    MethodName="CreateCustomers"
    />





    proizvod:

    (

    )


    x:Key="Šablon narudžbe"
    ItemsSource="(Putanja vezivanja=Detalji narudžbe)"
    ItemTemplate="(StaticResource OrderDetailTemplate)"
    >


    x:Key="CustomerTemplate"
    ItemsSource="(Obvezujući put=Narudžbe)"
    ItemTemplate="(StaticResource OrderTemplate)"
    >


    ItemsSource="(Binding Path=.)"
    ItemTemplate="(StaticResource CustomerTemplate)"
    />

    Dodjeljujem kolekciju Customer objekata u DataContext tabele (Grid) koja sadrži TreeView. U XAML kodu, to se može učiniti pomoću ObjectDataProvider, koji je na zgodan način pozivanje metode iz XAML-a. Budući da se DataContext nasljeđuje niz stablo elemenata, TreeView DataContext pruža referencu na ovaj skup objekata Customer. Iz tog razloga možemo dati njegovom svojstvu ItemsSource vezu "(Binding Path=.)", što je način da se ukaže da je svojstvo ItemsSource vezano za DataContext TreeView-a.

    Ako svojstvo ItemTemplate TreeViewa nije postavljeno na vrijednost, TreeView će prikazati samo objekte Kupca vrhunski nivo. Pošto WPF ne zna kako da prikaže klijenta, pozvaće ToString za svakog klijenta i prikazati taj tekst za svaki element. Neće imati načina da shvati da svaki Kupac ima listu objekata Order-a povezanih s njim, a svaki Order objekt ima listu OrderDetail objekata. Budući da WPF ne može na magičan način dati smisao postojećoj šemi podataka, potrebno je objasniti shemu WPF-u kako bi mogao ispravno vizualizirati strukturu podataka.

    HierarchicalDataTemplates dolaze u igru ​​kada treba da objasnite strukturu i izgled podataka WPF-u. Predlošci koji se koriste u ovoj demonstraciji sadrže vrlo jednostavna vizualna stabla, u osnovi samo polja TextBlock sa malom količinom teksta u njima. U složenijim aplikacijama, predlošci mogu imati interaktivno rotiranje 3D modeli, slike, vektorsku grafiku, složene korisničke kontrole ili bilo koji drugi WPF sadržaj dizajniran da prikaže osnovni objekt podataka.

    Važno je obratiti pažnju na redosled deklarisanja šablona. Predložak mora biti deklariran prije nego što se može referencirati kroz izraz StaticResource. Ovo je zahtjev koji nameće XAML čitač i odnosi se na sve resurse, a ne samo na šablone.

    Umjesto toga, predlošci se mogu referencirati pomoću izraza DynamicResource; u ovom slučaju, leksički red deklaracija šablona nije važan. Međutim, korištenje DynamicResource veza, za razliku od StaticResource veza, dolazi sa određenim troškovima izvršavanja jer prate promjene u sistemu resursa. Budući da ne zamjenjujemo šablone u vrijeme izvođenja, ovi dodatni troškovi su nepotrebni, pa je najbolje koristiti reference StaticResource i staviti deklaracije predložaka pravim redoslijedom.

    Rad sa korisničkim unosom

    Za većinu programa prikazivanje podataka je samo pola bitke. Drugi veliki izazov je raščlanjivanje, prihvaćanje i odbijanje korisničkog unosa. IN idealan svet, gdje svi korisnici uvijek unose logične i tačne podatke, to bi bio jednostavan zadatak. Ali u stvarnom svijetu to nije slučaj. Pravi korisnici napravite greške u kucanju, zaboravite da unesete tražene vrednosti, unesite vrednosti na pogrešna mesta, obrišite unose koje ne bi trebalo da se brišu, dodajte unose koje ne bi trebalo da se dodaju i generalno pratite Murphyjeve zakone gde god je to moguće.

    Naš posao kao programera i arhitekata je da se borimo protiv onoga što će korisnici neizbježno unijeti greškom ili zlonamjernom namjerom. WPF okvir za povezivanje podržava provjeru valjanosti unosa. U sljedećih nekoliko odjeljaka ovog članka, objasnit ću kako koristiti WPF-ovu podršku za validaciju, kao i kako prikazati poruke o grešci korisniku kada se otkriju greške u validaciji.

    Validacija unosa putem ValidationRules

    Prva verzija WPF-a, koja je bila dio Microsoft® .NET Framework 3.0, imala je samo ograničena podrška input checks. Klasa Binding imala je svojstvo ValidationRules koje je moglo pohraniti bilo koji broj klasa izvedenih iz ValidationRule. Svako od ovih pravila može sadržavati neku logiku koja provjerava da li je vezana vrijednost važeća.

    U to vrijeme, WPF je imao samo jednu potklasu ValidationRule pod nazivom ExceptionValidationRule. Programeri bi mogli da dodaju ovo pravilo svojstvu ValidationRules povezivanja, koje bi onda uhvatilo izuzetke bačene tokom ažuriranja izvora podataka, omogućavajući korisničkom interfejsu da prikaže poruku o grešci izuzetka. Korisnost ovog pristupa validaciji unosa je diskutabilna, s obzirom na to da je temelj dobrog korisničkog iskustva izbjegavanje izlaganja nepotrebnim tehničkim detaljima. Poruke o grešci u izuzecima analize podataka obično su takvi detalji za većinu korisnika, ali da se vratimo na našu temu.

    Recimo da imamo klasu koja predstavlja epohu vremena, kao što je jednostavna klasa Era prikazana ovdje:

    Javna klasa Era
    {

    }

    Ako želite dopustiti korisniku da promijeni datum početka i trajanje ere, možete koristiti dvije kontrole okvira za tekst i povezati njihova svojstva teksta sa svojstvima instance Era. Pošto korisnik može da unese šta god želi u tekstualno polje, ne postoji način da budemo sigurni da će tekst koji unese biti konvertovan u DateTime ili TimeSpan instancu. IN u ovom slučaju možete koristiti ExceptionValidationRule da prijavite greške u transformaciji podataka i zatim prikažete te greške u korisničkom interfejsu. U XAML kodu prikazanom na sl. Slika 11 pokazuje kako se ovaj zadatak može ostvariti.

    Rice. 11. Jednostavna klasa koja predstavlja vremensku epohu


    Datum početka:









    Trajanje:
    Grid.Row="3"
    Text="(Vezujuće
    Put=Trajanje

    />

    Ova dva tekstualna polja pokazuju dva načina na koja se ExceptionValidationRule može dodati svojstvu ValidationRules povezivanja u XAML-u. Tekstni okvir Datum početka koristi proširenu sintaksu elementa svojstva za direktno dodavanje pravila. Tekstni okvir Duration koristi skraćenu sintaksu koja jednostavno postavlja svojstvo vezivanja ValidatesOnExceptions na true. Oba vezivanja imaju svojstvo UpdateSourceTrigger postavljeno na PropertyChanged tako da se unos provjerava svaki put kada se svojstvu Text polja teksta dodijeli nova vrijednost, umjesto da se čeka dok kontrola ne izgubi fokus. Snimak ekrana programa prikazan je na Sl. 12.

    Rice. 12. ExceptionValidationRule prikazuje greške provjere valjanosti

    Prikaz grešaka u validaciji

    Kao što je prikazano na sl. 13, okvir za tekst Trajanje sadrži netačnu vrijednost. Niz koji sadrži nije konvertibilan u TimeSpan instancu. Tost poruka u tekstualnom okviru prikazuje poruku o grešci, a mala crvena ikona greške pojavljuje se na desnoj strani kontrole. Ovo ponašanje nije automatsko, ali ga je lako implementirati i prilagoditi konkretnom slučaju.

    Rice. 13. Vizualizacija grešaka otkrivenih prilikom verifikacije unosa za korisnika




    DockPanel.Dock="Desno"
    Margin="2.0"
    ToolTip="Sadrži nevažeće podatke"
    Širina="10" Visina="10"
    >











    Statička klasa Validacije formira odnos između kontrole i svih grešaka u validaciji koje sadrži korištenjem priloženih svojstava i statičkih metoda. Ova priložena svojstva mogu se referencirati u XAML-u za kreiranje opisa s jednim označavanjem kako bi korisničko sučelje trebalo korisniku prikazati greške na koje se susreću tijekom provjere valjanosti unosa. XAML kod na sl. 13 je odgovoran za objašnjenje kako prikazati poruke o grešci pri unosu za dvije kontrole okvira za tekst iz prethodnog primjera.

    Stil (“Stil”) na sl. 13 cilja na sve instance tekstualnog polja u korisničkom interfejsu. Na tekstualno polje primjenjuje tri parametra. Prvi, Setter, utiče na svojstvo Margin tekstualnog polja. Svojstvo Margin je postavljeno na vrijednost koja pruža dovoljno prostora za prikaz ikone greške na desnoj strani.

    Sljedeće svojstvo Setter u Style dodjeljuje ControlTemplate koji se koristi za prikazivanje tekstualnog polja kada sadrži nevažeće podatke. On postavlja priloženo svojstvo Validation.ErrorTemplate na ControlTemplate deklariran iznad Style. Kada klasa Validacija prijavi da je provjera valjanosti identificirala jednu ili više grešaka u tekstualnom polju, tekstualno polje prikazuje poruku koristeći ovaj predložak. To je ono što stvara crvenu ikonu greške prikazanu na slici. 12.

    Stil takođe sadrži okidač koji nadgleda svojstvo Validation.HasError prikačeno na tekstualno polje. Kada klasa Validation postavi priloženo svojstvo HasError na tačno za određeno tekstualno polje, okidač u stilu se aktivira i tekstualnom polju dodeljuje poruku zdravice. Sadržaj poruke zdravice vezan je za poruku o grešci iznimke koja se pojavi prilikom pokušaja konverzije teksta iz okvira za tekst u instancu tipa podataka svojstva izvora podataka.

    Provjera valjanosti unosa putem IDataErrorInfo

    Sa izdavanjem Microsoft .NET Frameworka 3.5, podrška za validaciju unosa u WPF-u je dramatično poboljšana. Pristup ValidationRule je koristan za jednostavne aplikacije, ali aplikacije iz stvarnog svijeta bave se složenošću podataka iz stvarnog svijeta i poslovnim pravilima. Kodiranje poslovnih pravila u objekte ValidationRule ne samo da povezuje taj kod sa WPF okvirom, već i sprečava da poslovna logika bude tamo gde joj je mesto: u poslovnim objektima!

    Mnoge aplikacije imaju poslovni sloj, gdje je sva složenost obrade poslovnih pravila sadržana u skupu poslovnih objekata. Kada se kompajlira u Microsoft .NET Framework 3.5, možete koristiti IDataErrorInfo sučelje da prisilite WPF da postavlja upite o poslovnim objektima bez obzira da li su u ispravnom stanju ili ne. Ovo eliminiše potrebu za postavljanjem poslovne logike u objekte odvojene od poslovnog sloja i omogućava vam da kreirate poslovne objekte koji su nezavisni od platforme korisničkog interfejsa. Budući da se IDataErrorInfo sučelje koristi već nekoliko godina, također olakšava ponovno korištenje poslovnih objekata iz starijih Windows Forms ili ASP.NET aplikacija.

    Pretpostavimo da želite da pružite provjeru valjanosti za epohu koja ide dalje od jednostavnog osiguranja da se tekst koji je dostavio korisnik može konvertirati u tip podataka svojstva izvora podataka. Možda ima smisla ne stavljati datum početka neke ere u budućnost, pošto ne znamo za ere koje tek dolaze. Zahtijevanje da epoha traje najmanje jednu milisekundu također može imati smisla.

    Ove vrste pravila su slične općoj ideji poslovne logike po tome što su oba primjera pravila opsega. Pravila opsega najbolje se kreiraju u objektima koji pohranjuju svoje stanje: objekti opsega. U kodu prikazanom na sl. 14 prikazuje klasu SmartEra, koja pruža poruke o greškama otkrivenim provjerom preko IDataErrorInfo interfejsa.

    Rice. 14. IDataErrorInfo pruža poruke o greškama otkrivenim provjerom

    javna klasa SmartEra
    : System.ComponentModel.IDataErrorInfo
    {
    javni DateTime StartDate ( get; set; )
    javno vremensko trajanje (dobi; postavi;)

    #region IDataErrorInfo Članovi

    javni string Greška
    {
    dobiti (vrati null; )
    }

    javni niz ovo
    {
    dobiti
    {
    string msg = null;
    prekidač (svojstvo)
    {
    slučaj "Datum početka":
    if (DateTime.Now< this.StartDate)
    msg = "Datum početka mora biti u prošlosti.";
    break;

    slučaj "Trajanje":
    if (this.Duration.Ticks == 0)
    msg = "Era mora imati trajanje.";
    break;

    zadano:
    baci novi ArgumentException(
    "Neprepoznato svojstvo: " + svojstvo);
    }
    return msg;
    }
    }

    #endregion // IDataErrorInfo Članovi
    }

    Korišćenje SmartEra podrške za validaciju klase iz WPF korisničkog interfejsa je veoma jednostavno. Vi samo trebate reći vezama da bi trebali prihvatiti IDataErrorInfo sučelje na objektu za koji su vezani. To se može učiniti na jedan od dva načina, kao što je prikazano na sl. 15.

    Rice. 15. Korištenje logike validacije


    Datum početka:










    Trajanje:
    Grid.Row="3"
    Text="(Vezujuće
    Put=Trajanje
    UpdateSourceTrigger=PropertyChanged,
    ValidatesOnDataErrors=Tačno,
    ValidatesOnExceptions=True)"
    />

    Baš kao što se ExceptionValidationRule može dodati u kolekciju ValidationRules vezanja eksplicitno ili implicitno, DataErrorValidationRule se može dodati direktno u ValidationRules povezivanja ili se svojstvo ValidatesOnDataErrors može postaviti na true. Oba pristupa imaju isti krajnji efekat - sistem povezivanja pita interfejs IDataErrorInfo izvora podataka za greške otkrivene provjerom.

    Sažimanje

    Postoji razlog zašto mnogi programeri kažu da je njihova omiljena WPF funkcija njegova opsežna podrška za povezivanje podataka. Mogućnosti povezivanja WPF-a su toliko moćne i prodorne da zahtijevaju od mnogih programera softvera da prilagode način na koji razmišljaju o odnosu između podataka i korisničkog sučelja. Mnoge osnovne komponente WPF-a rade zajedno kako bi podržale složene slučajeve povezivanja podataka, kao što su predlošci, stilovi i priložena svojstva.

    Sa relativno malo redova XAML koda, možete izraziti svoje namjere za prikaz hijerarhijske strukture podataka i validaciju korisničkog unosa. U složenijim situacijama, možete iskoristiti sve mogućnosti sistema povezivanja tako što ćete mu programski pristupiti. Sa tako moćnom infrastrukturom koja im je na raspolaganju, programeri koji grade moderne poslovne aplikacije mogu se konačno približiti postizanju svog prastarog cilja pružanja sjajnih korisničkih iskustava i uvjerljivih vizualizacija podataka.

    Posljednje ažuriranje: 02.07.2016

    U WPF-u, vezivanje je moćan alat za programiranje bez kojeg nijedna ozbiljna aplikacija ne može.

    Vezivanje uključuje interakciju dva objekta: izvora i odredišta. Odredišni objekt kreira vezivanje za određeno svojstvo izvornog objekta. Ako je izvorni objekt izmijenjen, odredišni objekt će također biti izmijenjen. Na primjer, najjednostavniji oblik koji koristi vezivanje:

    Za definiranje vezivanja, izraz poput:

    (Binding ElementName=Izvorno ime_objekta, Putanja=Svojstvo_izvornog objekta)

    To jest, u ovom slučaju, element TextBox je izvor, a TextBlock je odredište povezivanja. Svojstvo Text elementa TextBlock je vezano za svojstvo Text elementa TextBox. Kao rezultat toga, kada uđete u tekstualno polje, promjene u tekstualnom bloku će se dogoditi sinhrono.

    Rad sa uvezivanjem u C#

    Ključni objekat prilikom kreiranja povezivanja je System.Windows.Data.Binding objekat. Koristeći ovaj objekt možemo dobiti već postojeće vezivanje za element:

    Povezivanje vezivanja = BindingOperations.GetBinding(myTextBlock, TextBlock.TextProperty);

    U ovom slučaju, dobijamo vezivanje za svojstvo zavisnosti TextProperty elementa myTextBlock.

    Također možete postaviti vezivanje u potpunosti u C# kodu:

    Public MainWindow() ( InitializeComponent(); Binding binding = new Binding(); binding.ElementName = "myTextBox"; // izvorni element binding.Path = new PropertyPath("Text"); // svojstvo izvornog elementa myTextBlock. SetBinding( TextBlock.TextProperty, binding); // postavljanje vezivanja za element prijemnika)

    Ako nam u budućnosti više ne treba vezivanje, možemo koristiti klasu BindingOperations i njene metode ClearBinding() (uklanja jedno vezivanje) i ClearAllBindings() (uklanja sva vezivanja za dati element).

    BindingOperations.ClearBinding(myTextBlock, TextBlock.TextProperty);

    BindingOperations.ClearAllBindings(myTextBlock);

    Neka svojstva klase Binding:

      ElementName : ime elementa za koji se kreira vezivanje

      IsAsync: Ako je postavljeno na True, koristi asinhroni način za primanje podataka od objekta. Podrazumevano je False

      Mode : snap mod

      TargetNullValue : Postavlja zadanu vrijednost ako je vezano svojstvo izvora vezivanja null

      RelativeSource: Kreira vezivanje u odnosu na trenutni objekt

      Izvor : Pokazuje na izvorni objekt ako nije kontrola.

      XPath : koristi se umjesto svojstva putanje za specificiranje putanje do xml podataka

    Snap Modes

    Svojstvo Mode objekta Binding, koje predstavlja način povezivanja, može imati sljedeće vrijednosti:

      Jednosmjerni: Svojstvo odredišnog objekta se mijenja nakon što se modificira svojstvo izvornog objekta.

      OneTime: Svojstvo odredišnog objekta je samo jednom postavljeno na svojstvo izvornog objekta. Naknadne promjene izvora nemaju utjecaja na odredišni objekt.

      Dvosmjerni: I aplikacija i izvorni objekti mogu mijenjati međusobno povezana svojstva.

      OneWayToSource: Odredišni objekt u kojem je deklarirano vezivanje mijenja izvorni objekt.

      Podrazumevano : po defaultu (ako se promijeni svojstvo TextBox.Text, ono ima vrijednost Dvosmjerna, inače Jednosmjerna).

    Primjena snap moda:

    Obavezno ažuriranje. UpdateSourceTrigger

    Jednosmjerno povezivanje od izvora do prijemnika mijenja svojstvo prijemnika gotovo trenutno. Ali ako koristimo dvosmjerno vezivanje u slučaju tekstualnih polja (kao u primjeru iznad), onda kada se odredište promijeni, izvorno svojstvo se ne mijenja trenutno. Dakle, u gornjem primjeru, da bi se izvorno tekstualno polje promijenilo, moramo pomaknuti fokus sa odredišnog tekstualnog polja. I u ovom slučaju, svojstvo UpdateSourceTrigger klase Binding dolazi u igru, koje određuje kako će se ažuriranje dogoditi. Ovo svojstvo uzima jednu od vrijednosti nabrajanja UpdateSourceTrigger:

      PropertyChanged: Izvor vezivanja se ažurira odmah nakon ažuriranja svojstva u sinkronizaciji

      LostFocus: Izvor sidra se ažurira tek nakon što prijemnik izgubi fokus

      Eksplicitno: izvor se ne ažurira sve dok se ne pozove metoda BindingExpression.UpdateSource()

      Zadano: Zadana vrijednost. Za većinu svojstava, ovo je PropertyChanged . A za svojstvo Text elementa TextBox, ova vrijednost je LostFocus

    U ovom slučaju govorimo o ažuriranju izvora vezivanja nakon promjene odredišta u režimima OneWayToSource ili TwoWay. Odnosno, tako da se oba tekstualna polja koja su povezana dvosmjernim načinom trenutno ažuriraju nakon promjene jednog od njih, moramo koristiti vrijednost UpdateSourceTrigger.PropertyChanged:

    Izvorno svojstvo

    Svojstvo Source vam omogućava da postavite vezivanje čak i za objekte koji nisu WPF kontrole. Na primjer, definirajmo klasu telefona:

    Class Phone ( javni string Naslov ( get; set; ) javni niz Kompanija ( get; set; ) public int Price ( get; set; ) )

    Sada kreirajmo objekat ove klase i definirajmo vezivanje za njega:

    Svojstvo TargetNullValue

    U slučaju da svojstvo u izvoru vezivanja odjednom ima vrijednost null, odnosno nije postavljeno, možemo postaviti neku zadanu vrijednost. Na primjer:

    U ovom slučaju, resurs nexusPhone nema postavljeno svojstvo Title, tako da će blok teksta ispisati zadanu vrijednost specificiranu u parametru TargetNullValue.

    RelativeSource svojstvo

    Svojstvo RelativeSource vam omogućava da postavite vezivanje u odnosu na izvorni element koji ima neku vrstu odnosa sa odredišnim elementom. Na primjer, izvorni element može biti jedan od vanjskih spremnika za odredišni element. Ili izvor i odredište mogu biti isti element.

    Da biste postavili ovo svojstvo, koristite objekt RelativeSource istog imena. Ovaj objekt ima svojstvo Mode, koje specificira metodu povezivanja. Uzima jednu od vrijednosti nabrajanja RelativeSourceMode:

      Self: vezivanje se vrši za svojstvo istog elementa. To jest, izvorni element povezivanja je istovremeno i primatelj povezivanja.

      FindAncestor: vezivanje se vrši za svojstvo elementa kontejnera.

    Na primjer, kombinirajte izvorno i odredišno povezivanje u samom elementu:

    Ovdje su tekst i boja pozadine okvira za tekst povezani dvosmjernim povezivanjem. Kao rezultat, možemo vidjeti brojčanu vrijednost boje u polju, promijeniti je, a pozadina polja će se promijeniti zajedno s njom.

    Vezivanje na svojstva kontejnera:

    Kada koristite način FindAncestor, odnosno vezanje za kontejner, također morate specificirati parametar AncestorType i proslijediti mu tip kontejnera u obliku izraza AncestorType=(x:Type Container_element_type) . U ovom slučaju možemo odabrati bilo koji kontejner u stablu elemenata kao kontejner; konkretno, u ovom slučaju, pored Grid-a, takav kontejner je i element Window.

    DataContext svojstvo

    Objekt FrameworkElement od kojeg nasljeđuju kontrole ima zanimljivo svojstvo DataContext. Omogućava vam da postavite neki kontekst podataka za element i njegove ugniježđene elemente. Ugniježđeni elementi tada mogu koristiti objekt Binding da se vežu za određena svojstva tog konteksta. Na primjer, koristimo prethodno definiranu klasu Phone i kreirajmo kontekst podataka iz objekta ove klase:

    Na ovaj način postavljamo svojstvo DataContext na neki dinamički ili statički resurs. Zatim se vezujemo za ovaj resurs.

    Najbolji članci na ovu temu