Si të konfiguroni telefonat inteligjentë dhe PC. Portali informativ
  • në shtëpi
  • Windows 8
  • Konfigurimi i shfaqjes së të dhënave me lidhjen e të dhënave dhe WPF. Bazat e lidhjes së të dhënave WPF

Konfigurimi i shfaqjes së të dhënave me lidhjen e të dhënave dhe WPF. Bazat e lidhjes së të dhënave WPF

Shënim: Ky seksion mbulon konceptet bazë të lidhjes së të dhënave në WPF. Një numër shembujsh demonstrojnë aspektet themelore të lidhjes së elementeve të ndërfaqes me objektet vizuale dhe jo-vizuale WPF. Tema më serioze, të tilla si lidhja e elementeve të ndërfaqes së përdoruesit WPF me objekte dhe koleksione të shtypura me porosi, objekte të infrastrukturës ADO.NET dhe shabllone, do të trajtohen më vonë.

Pjesa I

Dispozitat e përgjithshme

Të gjitha programet e nevojshme për këtë punë mund të gjenden në katalogun e bashkangjitur.

Lidhja e të dhënave është një mekanizëm për nxjerrjen e informacionit nga objektet në elementët e ndërfaqes për shfaqje, dhe anasjelltas - shtyrjen e informacionit nga kontrollet në objekte. Lidhja e të dhënave ju lejon të bëni me pak ose aspak kodim. Kjo është një teknikë relativisht e vjetër, por në WPF ka marrë zhvillim të mëtejshëm dhe ka specifikat e veta. Të gjitha ndërlikimet e mbajtjes së lidhjes merren përsipër nga klasat e bibliotekës dhe koha e ekzekutimit. Lidhja mbulon një gamë të gjerë detyrash, nga lidhja e elementeve të thjeshta të ndërfaqes me njëri-tjetrin deri te lidhja e një baze të dhënash me format e ndërveprimit të të dhënave të personalizuara.

Ka gjithmonë dy palë të përfshira në lidhjen e të dhënave: burimi dhe destinacioni (objektivi) i informacionit. Lidhja e të dhënave mund të sigurojë shkëmbimin e të dhënave të njëanshme ose të dyanshme të vetive të ndërlidhura të objekteve. Lidhja me një drejtim më e përdorur, qëllimi i së cilës është nxjerrja e informacionit nga burimi dhe shfaqja e tij në marrës. Por në disa raste, dallimi midis burimit dhe marrësit fshihet, dhe ndonjëherë edhe rolet e tyre ndryshojnë - marrësi fillon t'i japë të dhëna burimit.

Sintaksa e lidhjes së të dhënave, si me burimet, ka gjithashtu dy shije: zgjerimet e shënjimit dhe elementet e pronësisë por ndryshon në detaje. Elementi kyç i lidhjes për çdo variacion është përcaktimi i një objekti Lidhja nga hapësira e emrave System.Windows.Data. Ky element vendoset gjithmonë në anën e marrësit të lidhjes, përveç në Mode = OneWayToSource. Marrësi duhet të rrjedhë nga klasa DependencyObject dhe vetia bindable (vetia e synuar) duhet të jetë prona e varësisë... Karakteristikat e varësisë kanë një aftësi të integruar për të dërguar ose marrë njoftime rreth ndryshimeve.

Ka shumë më pak kërkesa për burimin lidhës. Vetia e burimit të lidhshëm nuk duhet të jetë një pronë e varur. Gjëja kryesore është që burimi të ketë një ngjarje paralajmëruese që tregon një ndryshim në vetinë e detyrueshme. Burimi lidhës mund të jetë çdo pronë publike, duke përfshirë vetitë e kontrolleve të tjera, objektet CLR, elementët XAML, grupet e të dhënave ADO.NET, fragmentet XML, etj. WPF ofron dy klasa të specializuara, XmlDataProvider dhe ObjectDataProvider, për të aplikuar siç duhet lidhjen për objektet komplekse të të dhënave.

Quhen edhe vetitë e varësisë bashkangjitur... Në version XAML me qellim qe WPF, vetitë e bashkangjitura funksionojnë vetëm nëse lloji në të cilin është përcaktuar vetia dhe lloji të cilit i është bashkangjitur të dyja trashëgojnë nga klasa DependencyObject. Përdorimi i vetive të varësisë gjuhësore XAML ka aftësinë të zgjerojë llojet përmes vetive të ofruara nga lloje të tjera. Kur përdoret në shënjimin sipas sintaksës së elementeve të vetive, vetia e bashkangjitur gjithmonë paraprihet nga emri i llojit ofrues, edhe nëse vetia përdoret si atribut.

Udhëzimet e kapjes

Lloji i lidhjes së një elementi Binding përcaktohet nga vetia e tij Mode, e cila mund të jetë një nga vlerat e numërimit të BindingMode nga hapësira e emrave System.Windows.Data:

  • E paracaktuar- vendosur si parazgjedhje dhe varet nga lloji i vetive të lidhshme në anën e marrësit (vetia e synuar). Vepron si lidhje e dyfishtë për veçoritë e modifikueshme në ndërfaqen e përdoruesit, të tilla si TextBox.Text ose CheckBox.Checked, ose lidhje OneWay për vetitë e tjera. Për të shmangur mbështetjen në cilësimet e paracaktuara, është një ide e mirë që gjithmonë të vendosni në mënyrë eksplicite parametrin e drejtimit të ankorimit.
  • Njëkohë- lidhja fillestare njëkahëshe, kur vlera e vetive të synuar vendoset nga vlera e burimit vetëm një herë: gjatë inicializimit, zëvendësimi programatik i objektit të burimit të lidhur me një të ri, kur ndryshoni vetinë DataContext ose si rezultat i një programi thirrja e metodës BindingExpression.UpdateTarget(). Njoftimet e tjera hyrëse të ndryshimeve në anën e burimit nuk do të merren parasysh nga marrësi.
  • Një mënyrë- lidhje me një drejtim, ku vetia e synuar përditësohet kur ndryshon vetia e burimit. Sa herë që bëhet një ndryshim në anën e burimit, rrjedha e të dhënave drejtohet nga burimi në objektiv.
  • OneWayToSource- organizon lidhjen me një drejtim, si OneWay, vetëm shprehja lidhëse vendoset në burim. Ky truk është i dobishëm kur vetia e synuar e bindueshme nuk është një veti varësie, por vetia e burimit ende trashëgon nga klasa DependencyObject.
  • Dykahëshe- lidhje me dy drejtime, ku vetia e synuar përditësohet kur vetia e burimit ndryshon dhe vetia e burimit përditësohet kur vetia e synuar ndryshon. Me fjalë të tjera, mënyra e lidhjes TwoWay dërgon të dhëna nga burimi në objektiv dhe nëse vlera e vetive të objektivit ndryshon, të dhënat kthehen nga objektivi në burim.

Ushtrimi 1: Lidhni një artikull me një artikull

Në këtë ushtrim, duke përdorur një sërë shembujsh, ne do të shqyrtojmë çështjet e krijimit të një kanali komunikimi midis vetive të varësisë së elementeve vizuale WPF të ndërfaqes së përdoruesit.

>

Lidhja e të dhënave në XAML

Ndarja e objekteve në një skedar XAML mund të bëhet gjithashtu përmes lidhjes së të dhënave. Në fakt lidhja e të dhënave bashkon dy veti të objekteve të ndryshme. Siç do ta shihni më vonë, lidhjet e të dhënave përdoren më shpesh për të lidhur pamjet vizuale të faqeve me burimet e të dhënave; përveç kësaj, ato janë një pjesë e rëndësishme e zbatimit të modelit arkitektonik popullor MVVM (Model-View-ViewModel)... Lidhjet gjithashtu luajnë një rol të rëndësishëm në përcaktimin e modeleve të shfaqjes së objekteve të të dhënave.

Lidhjet e të dhënave mund të përdoren për të lidhur vetitë e dy artikujve. Element lidhës Ashtu si StaticResource, ai zakonisht shprehet si një zgjatim shënjimi, domethënë është i mbyllur në kllapa kaçurrelë. Megjithatë, elementi Binding pranon gjithashtu një shprehje alternative në sintaksën e elementit të vetive.

Përdorni fjalorin e burimeve të mëposhtme në projektin tonë të testimit:

Cilësimet e furçës

Stili i nënkuptuar i TextBlock nuk përmban një veçori Foreground. Një LinearGradientBrush është përcaktuar për të parën nga katër elementët TextBlock duke përdorur këtë brush, dhe elementët pasues të TextBlock i referohen të njëjtës furçë përmes ankorimit:

Lidhja e të dhënave ka burimi dhe objektiv... Marrësi është gjithmonë vetia me të cilën është vendosur lidhja, dhe burimi është vetia me të cilën është lidhur. Lidhjet e listuara janë me burim nga një TextBlock i quajtur topTxb; sinks janë tre elementë TextBlock që ndajnë veçorinë Foreground. Dy marrës përfaqësojnë një mënyrë më standarde për të shprehur një objekt Lidhja si një shtrirje shënjimi XAML:

(Emri i elementit lidhës = topTxb, shtegu = plan i parë)

Zgjatjet e shënjimit XAML janë gjithmonë të mbyllura në mbajtëse kaçurrelë. Në një shtesë shënjimi për Lidhje, zakonisht duhet të vendosni një palë veçori, të ndara me presje. Vetia Emri i elementit tregon emrin e elementit për të cilin është vendosur vetia e dëshiruar; Vetia e shtegut jep emrin e pronës.

Kur shkruaj shtesat e shënjimit të lidhjes, gjithmonë dua të citoj vlerat e vetive, por kjo është e gabuar. Thonjëzat nuk nevojiten në shprehjet e ankorimit.

Elementi i fundit TextBlock demonstron shprehjen Binding në sintaksën e elementit të vetive më pak të zakonshme:

Në këtë sintaksë, kërkohen thonjëza rreth vlerave të pronave sepse këto janë atribute normale XML. Ju gjithashtu mund të krijoni një objekt Lidhja në kod dhe t'ia caktoni atë një vetie marrëse duke përdorur metodën SetBinding () të përcaktuara në FrameworkElement. Kjo e bën të qartë se marrësi lidhës duhet të jetë gjithmonë një veti varësie.

Vetia Path e klasës Binding është quajtur kështu sepse mund të përmbajë emra të shumëfishtë të vetive, të ndara me pika. Për shembull, provoni të zëvendësoni një nga vlerat e tekstit në projektin tuaj me vlerën e mëposhtme:

Teksti = "(Emri i elementit lidhës = topTxb, Shtegu = FontFamily. Burimi)"

Pjesa e parë e shtegut tregon se na duhen të dhëna nga vetia FontFamily. Vetia vendoset në një objekt të tipit FontFamily që përmban një Burim të emërtuar që tregon emrin e familjes së fontit. Prandaj, teksti "Arial" do të shfaqet në TextBlock.

Provoni të aplikoni konstruktin e mëposhtëm në çdo element TextBlock në projektin tonë:

Teksti = "(Binding RelativeSource = (RelativeSource Self), Shtegu = FontSize)"

Këtu është një zgjerim shënjimi Burimi Relativështë brenda zgjerimit të shënjimit Binding dhe përdoret për t'iu referuar një vetie të elementit të cilit i vendoset lidhja.

  • Programimi
  • Një nga pikat kryesore të zhvillimit xaml-aplikacionet e orientuara është përdorimi i lidhjeve ( Lidhjet). Lidhja- atë ndërmjetësues(ndërmjetësi) që sinkronizon vlerat e pronave ndërmjet objekteve të lidhura.

    Vlen të përmendet një nuancë e dukshme, por e rëndësishme: megjithëse lidhja i referohet objekteve që ndërveprojnë në një mënyrë ose në një tjetër, nuk i ruan ato nga grumbullimi i mbeturinave!

    Trashëgimia e klasës Lidhja lejohet, por për arsye sigurie të kodit, duke anashkaluar metodën Ofroni vlerë që lidhet me logjikën kryesore të punës nuk lejohet. Kjo disi i provokon zhvilluesit të përdorin modelin. Konvertuesi e cila është e ndërlidhur ngushtë me temën e lidhjeve.

    Lidhjet janë një mjet shumë i fuqishëm, por në disa raste deklarimi i tyre rezulton i zhdërvjellët dhe i papërshtatshëm kur përdoret rregullisht, për shembull, për lokalizim. Në këtë artikull, ne do t'ju tregojmë një mënyrë të thjeshtë dhe elegante për ta bërë kodin tuaj shumë më të pastër dhe më të bukur.


    Shpallni detyrimet në xaml e vlefshme në dy mënyra:



    Natyrisht, metoda e parë nuk duket shumë koncize, e dyta, bazuar në përdorimin e zgjerimet e shënjimit, përdoret më shpesh. Në platformë WPF ka një mundësi për të krijuar shtesat e shënjimit me porosi... Për shembull, ato janë të dobishme për lokalizim.


    Në rastin më të thjeshtë, ju duhet të trashëgoni nga klasa Markup Extension dhe zbatoni metodën Ofroni vlerë, në të cilën për të marrë vlerën e dëshiruar me çelës.

    Megjithatë, një zbatim i tillë nuk mbështet ndryshimin e gjuhës së nxehtë gjatë ekzekutimit të programit. Për të bërë këtë përmirësim, është e nevojshme, së pari, të ruhet një referencë për elementin e ndërfaqes së lokalizueshme, dhe së dyti, e cila është më pak e dukshme, në një mënyrë ose në një tjetër në aplikacion të ketë një referencë për vetë shembullin e klasës. Lokalizimi, për ta mbrojtur atë nga grumbullimi i plehrave dhe, së treti, kërkohet të zbatohet saktë abonimi dhe çregjistrimi nga ngjarja e ndryshimit të gjuhës.

    Nëse i bëni këto gjëra gabimisht, ju garantohet se do të keni rrjedhje memorie nëse pamjet krijohen dhe zhduken në mënyrë dinamike gjatë ekzekutimit të aplikacionit, dhe në shumë raste ky është rasti. Kjo do të thotë, duke shtuar një funksion në dukje jo më kompleks, do t'ju duhet të merreni me tema jo të parëndësishme lidhjet e pllakave dhe abonime të dobëta në ngjarje... Dhe kodi nuk është shumë i thjeshtë.

    Për më tepër, në xaml-platformat Windows Phone, Dyqani i Windows dhe Xamarin.Format nuk ka asnjë mënyrë për të krijuar shtesa të shënjimit me porosi, gjë që çon në idenë e përdorimit të lidhjeve si zgjerime të shënjimit

    Le të mos rrahim rreth shkurret, ja çfarë na duhet:

    Klasa abstrakte publike BindingExtension: Binding, IValueConverter (BindingExtension i mbrojtur () (Burimi = Konvertuesi = kjo;) i mbrojtur BindingExtension (burimi i objektit) // vendos Burimi në null për përdorimin e DataContext (Burimi = burimi; Konvertuesi = ky;) i mbrojtur BindingelStensioni (R. relativeSource) (RelativeSource = Burimi i afërm; Konvertuesi = ky;) objekt abstrakt publik Konvertoj (vlera e objektit, Lloji targetType, parametri i objektit, kultura CultureInfo); objekti virtual publik ConvertBack (vlera e objektit, Lloji targetType, parametri i objektit, kultura CultureInfo) (hedh të re NotImplementedException ();))
    Vlen të përmendet se lidhja është një konvertues për vete. Si rezultat, ne marrim sjellje shumë të ngjashme, si kur trashëgojmë nga një klasë. Markup Extension por gjithashtu është ende e mundur të përdoren mekanizmat standardë të kontrollit të grumbullimit të plehrave!

    Tani logjika për lokalizimin nuk duket askund më e thjeshtë:

    Klasa publike e pjesshme Localizing: Base.BindingExtension (public static only reading Manager ActiveManager = new Manager (); Public Localizing () (Burimi = ActiveManager; Rruga = PropertyPath i ri ("Burimi");) Localizimi publik (çelës i vargut) (Key = çelës ; Burimi = ActiveManager; Shtegu = PropertyPath i ri ("Burimi");) vargu publik Çelësi (merr; vendos;) objekti i zëvendësimit publik Konverto (vlera e objektit, Lloji targetType, parametri i objektit, kultura CultureInfo) (kyç var = Kyç; var burimManager = vlera si ResourceManager; var localizedValue = resourceManager == null || string.IsNullOrEmpty (çelës)? ":" + çelësi + ":": (resourceManager.GetString (çelësi) ?? ":" + çelësi + ":") ; ktheni vlerën e lokalizuar;))
    lokalizimi i klasës së pjesshme publike (Menaxheri i klasës publike: INotifyPropertyChanged (private ResourceManager _source; Burimi publik i ResourceManager (merr (ktheje _source;) grup (_source = vlerë; PropertyChanged (kjo, PropertyChangedEventArgs i ri ("Burimi"))) vargu publik Merr ("Source");)) çelësi i vargut, string stringFormat = null) (nëse (_source == null || string.IsNullOrWhiteSpace (çelësi)) çelësi i kthimit; var localizedValue = _source.GetString (çelës) ?? ":" + çelësi + ":"; kthimi vargun .IsNullOrEmpty (stringFormat)? LocalizedValue: string.Format (stringFormat, localizedValue);) ngjarje publike PropertyChangedEventHandler PropertyChanged = (dërguesi, args) => ();))
    Është e lehtë të shtohet aftësia për të ndryshuar madhësinë e shkronjave:

    Klasa e pjesshme publike Localizimi: Base.BindingExtension (Numri publik Rastet (Default, Lower, Upper) statike publike vetëm për lexim Menaxher ActiveManager = Menaxheri i ri (); Lokalizimi publik () (Burimi = ActiveManager; Shtegu = PropertyPath i ri ("Burimi");) Lokalizimi publik (çelësi i vargut) (Key = çelës; Burimi = ActiveManager; Shtegu = PropertyPath i ri ("Burimi");) vargu publik Çelësi (merr; vendos;) Rasti publik i rasteve (merr; vendos;) vargu publik i zëvendësimit ToString () (ktheje Convert (ActiveManager.Source, null, Key, Thread.CurrentThread.CurrentCulture) si varg ?? string.Empty;) objekti i zëvendësimit publik Konverto (vlera e objektit, Lloji targetType, parametri i objektit, kultura CultureInfo) (kyç var = Key; var resourceManager = vlera si ResourceManager; var localizedValue = resourceManager == null || string.IsNullOrEmpty (çelës)? ":" + çelësi + ":": (resourceManager.GetString (çelësi) ?? ":" + çelësi + ": "); kaloni (Rastet e rastit) (Raset e rastit. Më të ulëta: ktheni vlerën e lokalizuar.Tomë të ulët (); rastet e rasteve. E sipërme: kthen vlerën e lokalizuar.ToUpper (); default: kthen vlerën e lokalizuar; )))
    V xaml hyrja duket e bukur dhe e këndshme, por ka disa kufizime të analizuesve të shënjimit në platforma të ndryshme:


    Për të hequr qafe në WPF nga parashtesa e kërkuar m: ju duhet të vendosni zgjerimin e shënjimit në një asamble të veçantë dhe brenda Vetitë / AssemblyInfo.cs specifikoni direktivat e mëposhtme:


    Për të rregulluar emrin e prefiksit në Windows Phone ose Dyqani:


    Përdorimi i shtesave lidhëse ( Zgjatjet lidhëse) në WPF nuk përjashton zgjerimet e zakonshme të shënjimit, por është edhe më i sigurt dhe më i lehtë në disa raste. Gjithashtu, e gjithë kjo nuk kufizohet vetëm në një lokalizim, por është e përshtatshme për shumë qëllime të tjera ...

    Qasja e demonstruar përdoret shumë në bibliotekë

    Kur Windows Presentation Foundation (WPF) erdhi për herë të parë në vëmendjen e .NET, shumica e artikujve dhe demo-ve lartësuan motorin e tij të lartë të paraqitjes dhe aftësitë 3D. Ndonëse janë argëtuese për t'u lexuar dhe luajtur me to, këta shembuj nuk pasqyrojnë aftësitë e gjëra të botës reale të WPF. Shumica prej nesh nuk kanë nevojë të krijojnë aplikacione kubike video rrotulluese që shpërthejnë si fishekzjarre kur klikohen. Shumica prej nesh sigurojnë jetesën duke krijuar softuer për shfaqjen dhe redaktimin e vëllimeve të mëdha të të dhënave komplekse shkencore ose të biznesit.

    Lajmi i mirë është se WPF ofron mbështetje të shkëlqyer për manipulimin e shfaqjes dhe redaktimin e të dhënave komplekse. Në numrin e dhjetorit 2007 të MSDN® Magazine, John Papa shkroi artikullin "Lidhja e të dhënave në WPF" (msdn.microsoft.com/magazine/cc163299) që shpjegon në mënyrë të shkëlqyer konceptet kryesore të lidhjes së të dhënave në WPF. Këtu, unë do të kaloj në rastet më të avancuara të lidhjes së të dhënave, duke u mbështetur në atë që John prezantoi në numrin e lartpërmendur të Data Points. Pas leximit, lexuesit do të jenë të vetëdijshëm për mënyrat e ndryshme për të zbatuar kërkesat e përbashkëta të lidhjes së të dhënave që shihen në shumicën e aplikacioneve të biznesit.

    Lidhja në kod

    Një nga ndryshimet më të mëdha që WPF prezanton për zhvilluesit e desktopit është përdorimi dhe mbështetja e gjerë për programimin deklarativ. Ndërfaqet dhe burimet e përdoruesve të WPF mund të deklarohen duke përdorur gjuhën e shënjimit të aplikacionit të zgjeruar (XAML), një gjuhë standarde shënjimi e bazuar në XML. Shumica e shpjegimeve të lidhjes së të dhënave WPF tregojnë vetëm se si të punohet me lidhjet në XAML. Meqenëse gjithçka që mund të bëhet në XAML mund të arrihet edhe në kod, është e rëndësishme që zhvilluesit profesionistë të WPF të dinë të punojnë me lidhjen e të dhënave jo vetëm në mënyrë deklarative, por edhe programore.

    Në shumë raste, është më e lehtë dhe më e përshtatshme të deklarohen lidhjet në XAML. Ndërsa sistemet bëhen më komplekse dhe dinamike, ndonjëherë ka kuptim të punoni me lidhjet në kodin tuaj. Përpara se të shkojmë më tej, le të hedhim një vështrim në disa nga klasat dhe metodat e zakonshme të përfshira në lidhjen programatike të të dhënave.

    Elementet WPF trashëgojnë metodat SetBinding dhe GetBindingExpression nga FrameworkElement ose FrameworkContentElement. Ato janë thjesht metoda të përdorshmërisë që thërrasin metoda me të njëjtin emra në klasën e shërbimeve BindingOperations. Kodi i mëposhtëm tregon se si të përdoret klasa BindingOperations për të lidhur veçorinë Text të një kutie teksti me një pronë në një objekt tjetër:

    Static void BindText (TextBox textBox, veti e vargut)
    {
    if (! BindingOperations.IsDataBound (TextBox, textProp))
    {
    Lidhja b = e re Lidhja (vetia);
    BindingOperations.SetBinding (TextBox, textProp, b);
    }
    }

    Mund ta zhbllokoni lehtësisht një pronë duke përdorur kodin e mëposhtëm:

    UnbindText statik i zbrazët (TextBox textBox)
    {
    DependencyProperty textProp = TextBox.TextProperty;
    nëse (BindingOperations.IsDataBound (TextBox, textProp))
    {
    BindingOperations.ClearBinding (TextBox, textProp);
    }
    }

    Pastrimi i lidhjes gjithashtu heq vlerën e lidhur nga vetia e synuar.

    Një deklaratë e detyrueshme e të dhënave në XAML fsheh disa nga detajet themelore. Kur filloni të punoni me lidhjet në kod, këto detaje fillojnë të notojnë në sipërfaqe. Njëra është se marrëdhënia midis burimit të një lidhjeje dhe objektivit të saj mbahet në të vërtetë nga një shembull i klasës BindingExpression, dhe jo nga vetë Binding. Klasa Binding përmban informacion të nivelit të lartë që mund të ndajnë klasa të shumta BindingExpression, por shprehja themelore zbaton lidhjen midis dy vetive të lidhura. Kodi i mëposhtëm tregon se si BindingExpression mund të përdoret për të verifikuar në mënyrë programore nëse veçoria Text e një kutie teksti është e kontrolluar:

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

    var expr = textBox.GetBindingExpression (textProp);
    nëse (expr == null)
    kthej false;

    Lidhja b = expr.ParentLidhja;
    kthimi b.ValidationRules.Any ();
    }

    Për shkak se klasa BindingExpression nuk e di se është duke u testuar, ju duhet të pyesni lidhjen e saj prind. Më poshtë do të diskutoj teknikat e ndryshme të vërtetimit të hyrjes.

    Puna me shabllone

    Një ndërfaqe efikase e përdoruesit paraqet të dhënat e papërpunuara në atë mënyrë që përdoruesi të mund të nxjerrë në mënyrë intuitive informacion kuptimplotë prej tyre. Ky është thelbi i vizualizimit të të dhënave. Lidhja e të dhënave është vetëm një pjesë e enigmës së vizualizimit të të dhënave. Të gjithë programet WPF, përveç atyre më të parëndësishme, kërkojnë një mënyrë për të përfaqësuar të dhënat që është më e fuqishme sesa thjesht lidhja e një vetie në një kontroll me një veçori të vetme në një objekt të dhënash. Objektet reale të të dhënave kanë shumë veti të lidhura me to, dhe këto veti të ndryshme duhet të konvergojnë në një paraqitje vizuale koherente. Për këtë arsye, WPF ka shabllone të dhënash.

    Klasa System.Windows.DataTemplate është vetëm një formë e shabllonit në WPF. Në thelb, një shabllon është një prerës skedari që korniza WPF përdor për të krijuar pamje vizuale për të ndihmuar në paraqitjen e objekteve që nuk kanë një paraqitje vizuale të tyren. Kur një element përpiqet të japë një objekt që nuk ka një paraqitje të tillë, të themi, një objekt biznesi të personalizuar, ju mund t'i tregoni elementit se si ta përshkruajë objektin duke i dhënë një DataTemplate.
    DataTemplate mund të krijojë sa më shumë pamje vizuale që nevojiten për të shfaqur objektin e të dhënave. Këta elementë përdorin lidhje të dhënash për të shfaqur vlerën e vetive të një objekti të dhënash. Nëse elementi nuk di se si të shfaqë objektin që i është thënë të renderojë, ai thjesht thërret metodën ToString në të dhe i shfaq rezultatet në një TextBlock.

    Supozoni se kemi një klasë të thjeshtë të quajtur FullName që ruan emrin e një personi. Është e nevojshme të shfaqet një listë emrash në të cilat mbiemri i secilit person do të dallohej nga të tjerët. Për ta bërë këtë, mund të krijoni një DataTemplate që përshkruan se si të jepet një objekt FullName. Kodi i paraqitur në Fig. 1, shfaq klasën FullName dhe kodin e sfondit për një dritare që shfaq një listë emrash.

    Oriz. 1. Shfaqja e objekteve FullName duke përdorur DataTemplate

    klasë publike Emri i plotë
    {
    vargu publik FirstName (merr; vendos;)
    karakter publik MiddleInitial (merr; vendos;)
    vargu publik Mbiemri (merr; vendos;)
    }

    klasë publike e pjesshme WorkingWithTemplates: Dritare
    {
    // Ky është konstruktori i dritares.
    publike WorkingWithTemplates ()
    {
    InitializeComponent ();

    bazë.DataContext = emri i plotë i ri
    {
    i ri Emri i plotë
    {
    Emri = "Johann",
    Fillimi i mesëm = "S",
    Mbiemri = "Bach"
    },
    i ri Emri i plotë
    {
    Emri = "Gustav",
    Fillimi i mesëm = "",
    Mbiemri = "Mahler"
    },
    i ri Emri i plotë
    {
    Emri = "Alfred",
    Fillimi i mesëm = "G",
    Mbiemri = "Schnittke"
    }
    };
    }
    }

    Siç mund të shihet në Fig. 2, ekziston një ItemsControl në skedarin XAML të dritares. Krijon një listë të thjeshtë artikujsh që përdoruesi nuk mund t'i zgjedhë ose heqë. ItemsControl ka një DataTemplate të shtrirë në vetinë e tij ItemTemplate me të cilën ai jep çdo shembull FullName të krijuar në konstruktorin e dritares. Do të vini re se shumica e elementeve TextBlock në DataTemplate e kanë veçorinë e tyre Text të lidhur me vetitë që përfaqësojnë në objektin FullName.

    Oriz. 2. Shfaqja e objekteve FullName duke përdorur DataTemplate














    Kur ekzekutoni këtë aplikacion demo, duket si Fig. 3. Përdorimi i DataTemplate për të dhënë emrin e parë e bën të lehtë nxjerrjen në pah të mbiemrit të çdo personi, sepse parametri FontWeight i TextBlock-it përkatës është i theksuar. Ky shembull i thjeshtë tregon thelbin e marrëdhënies midis lidhjes së të dhënave WPF dhe shablloneve. Ndërsa gërmoj më thellë në temë, do t'i kombinoj këto funksione, duke krijuar mënyra për të paraqitur objekte komplekse me gjithnjë e më shumë aftësi.

    Oriz. 3. Objektet FullName të paraqitura nga DataTemplate

    Puna me të dhënat e trashëguara

    Nëse nuk shënohet ndryshe, të gjitha lidhjet lidhen në mënyrë implicite me veçorinë DataContext të artikullit. DataContext i një elementi i referohet burimit të tij të të dhënave, si të thuash. Ka disa gjëra të veçanta për të ditur se si funksionon DataContext. Kuptimi i këtij aspekti të nënkuptuar të DataContext e bën shumë më të lehtë hartimin e ndërfaqeve komplekse të përdoruesit të lidhura me të dhënat.

    Ju nuk keni nevojë të vendosni vetinë DataContext për t'iu referuar një objekti burimi të të dhënave. Nëse vetive DataContext e një elementi paraardhës në një pemë elementi (teknikisht, një pemë logjike) i jepet një vlerë për DataContext-in e tij, atëherë vlera do të trashëgohet automatikisht nga secili element i prejardhur në ndërfaqen e përdoruesit. Me fjalë të tjera, nëse DataContext është caktuar t'i referohet një objekti Foo, atëherë, si parazgjedhje, DataContext i çdo artikulli në dritare do t'i referohet të njëjtit objekt Foo. Çdo elementi në një dritare mund t'i jepet lehtësisht vlera e tij DataContext, e cila do të bëjë që të gjithë elementët që rrjedhin nga ai element të trashëgojnë vlerën e re të DataContext. Kjo është e ngjashme me një pronë të jashtme në Windows Forms.

    Në seksionin e mëparshëm, shikova përdorimin e DataTemplates për të krijuar vizualizime të objekteve të të dhënave. Vetitë e elementeve të krijuara nga shablloni në Fig. 2 janë të lidhura me vetitë e objektit FullName. Këta elementë lidhen në mënyrë implicite me vetinë e tyre DataContext. Vetia DataContext e elementeve të krijuar nga DataTemplate i referohet objektit të të dhënave për të cilin përdoret shablloni, siç është objekti FullName.

    Nuk ka magji për të trashëguar një vlerë nga vetia DataContext. Thjesht po përdor mbështetjen e integruar të WPF për vetitë e varësisë së trashëguar. Çdo pronë e varësisë mund të jetë një pronë e trashëguar nëse thjesht shënohet në meta të dhënat e dhëna kur ajo pronë është regjistruar në Sistemin e Pronave të Varësisë WPF.

    Një shembull tjetër i një veçorie të varësisë së trashëguar është vetia Font-Size që kanë të gjithë elementët. Nëse vendosni veçorinë e varësisë së FontSize në një dritare, atëherë si parazgjedhje të gjithë elementët në këtë dritare do të shfaqen si tekst në madhësinë e specifikuar të fontit. Infrastruktura e përdorur për të përhapur vlerën FontSize poshtë pemës së elementit përhap gjithashtu DataContext.

    Këtu, termi "trashëgimi" përdoret me një kuptim të ndryshëm nga kuptimi i tij i orientuar nga objekti, ku një nënklasë trashëgon anëtarët e një klase mëmë. Trashëgimia e vlerës së pronës zbatohet vetëm për përhapjen e vlerave në pemën e elementit në kohën e ekzekutimit. Natyrisht, një klasë mund të trashëgojë një veti varësie për të mbështetur trashëgiminë e vlerës në një kuptim të orientuar nga objekti.

    Puna me pamjet e koleksionit

    Kur kontrollet e WPF lidhen me një koleksion të dhënash, ato nuk lidhen drejtpërdrejt me vetë koleksionin. Në vend të kësaj, ato lidhen në mënyrë implicite me një pamje që përfundon automatikisht rreth atij koleksioni. Pamja zbaton ndërfaqen ICollectionViews dhe mund të jetë një nga disa implementime konkrete si ListCollectionView.

    Prezantimi i koleksionit ka disa detyra. Mban gjurmët e artikullit aktual në koleksion, i cili zakonisht është artikulli i zgjedhur / aktiv në kontrollin e listës. Pamjet e koleksionit ofrojnë gjithashtu mënyra të përgjithshme për të organizuar, filtruar dhe grupuar artikujt në një listë. Kontrollet e shumta mund të lidhen me të njëjtën pamje rreth koleksionit, duke siguruar koordinimin e tyre me njëri-tjetrin. Kodi më poshtë tregon disa nga aftësitë e ICollectionView:

    // Merrni pamjen e paracaktuar të mbështjellë rreth listës së klientëve.
    Pamja ICollectionView = CollectionViewSource.GetDefaultView (të gjithë klientët);

    // Zgjedhja e klientit në ndërfaqen e përdoruesit.
    Klienti i zgjedhurKlienti = pamje.Artikulli aktual si klient;

    // Vendosni klientin e zgjedhur në ndërfaqen e përdoruesit.
    pamje.MoveCurrentTo (dikush Tjetër Klient);

    Të gjitha kontrollet e llojit të listës, duke përfshirë kutitë e listave, kutitë e kombinuara dhe pamjet e listës, duhet të kenë veçorinë e tyre IsSynchronizedWithCurrentItem të caktuar në true për të qëndruar në sinkron me veçorinë e pamjes CurrentItem të koleksionit. Kjo veti përcakton klasën Abstrakt Selector. Nëse nuk është vendosur në true, atëherë zgjedhja e një artikulli në kontrollin e listës nuk do të përditësojë CurrentItem të pamjes së koleksionit dhe caktimi i një vlere të re për CurrentItem nuk do të shfaqet në kontrollin e listës.

    Puna me të dhëna hierarkike

    Bota reale është plot me të dhëna hierarkike. Një klient bën disa porosi, një molekulë përbëhet nga shumë atome, një departament përbëhet nga shumë punonjës dhe sistemi diellor përmban një grup trupash qiellorë. Lexuesit pa dyshim do të jenë të njohur me këtë skemë master / detaje.
    WPF ofron një shumëllojshmëri mënyrash për të punuar me strukturat hierarkike të të dhënave, secila e përshtatshme për situata të ndryshme. Në thelb, alternativa zbret në përdorimin e kontrolleve të shumta për të shfaqur të dhënat, ose shfaqjen e niveleve të shumta të hierarkisë së të dhënave në një kontroll të vetëm. Unë do t'i mbuloj të dyja këto qasje këtu.

    Përdorimi i kontrolleve të shumta për të shfaqur të dhënat XML

    Një mënyrë shumë e zakonshme e punës me të dhënat hierarkike është shfaqja e çdo niveli të hierarkisë si një kontroll i veçantë. Për shembull, le të themi se kemi një sistem që përfaqëson klientët, porositë dhe detajet e porosive. Në një situatë të tillë, një kuti kombinuese mund të përdoret për të shfaqur klientët, një kuti liste për të shfaqur të gjitha porositë e klientëve të zgjedhur dhe në fund ItemsControl për të shfaqur detajet e porosisë së zgjedhur. Është një mënyrë e shkëlqyeshme për të shfaqur të dhëna hierarkike dhe është shumë e lehtë për t'u zbatuar në WPF.

    Në Fig. 4, bazuar në situatën e përshkruar më sipër, tregon një shembull të thjeshtuar të të dhënave që një aplikacion mund të trajtojë, të mbështjellë në një WPF XmlDataProvider. Këto të dhëna mund të shfaqen në një ndërfaqe përdoruesi të ngjashme me atë të treguar në Fig. 5. Vini re se klientët dhe porositë janë të zgjidhshme, por informacioni i porosisë është në formën e listës vetëm për lexim. Ekziston një arsye për këtë - aftësia për të zgjedhur një objekt vizual duhet të sigurohet vetëm kur ai ndikon në gjendjen e aplikacionit ose është i ndryshueshëm.

    Oriz. 4. Hierarkia e porosive të klientëve dhe informacioni i porosive në formatin XML





















    Oriz. 5 Një mënyrë për të shfaqur të dhënat XML

    XAML në Fig. 6 përshkruan se si të përdoren këto kontrolle të ndryshme për të shfaqur të dhënat hierarkike të sapo shfaqura. Kjo dritare nuk kërkon ndonjë kod; ekziston tërësisht në XAML.

    Oriz. 6. Kodi XAML për të lidhur të dhënat hierarkike XML me ndërfaqen e përdoruesit

    "(Burimi i lidhjes = (StaticResource xmlData),
    XPath = klientë / klient) "
    Marzhi = "4"
    >







    ItemsSource = "(Lidhja)"
    >









    x: Emri = "orderSelector"
    DataContext = "(Rruga lidhëse = CurrentItem)"
    IsSynchronizedWithCurrentItem = "E vërtetë"
    ItemsSource = "(Lidhja XPath = porosi)"
    >








    Tekst = "Detajet e porosisë" />
    Konteksti i të Dhënave =
    "(Emri i elementit lidhës = zgjedhësi i porosisë, shtegu = artikulli i zgjedhur)"
    ItemsSource = "(Binding XPath = orderDetail)">



    Produkt:

    (

    )





    Vini re përdorimin e gjerë të pyetjeve të shkurtra XPath për t'i treguar WPF se ku mund të marrë vlerat e lidhura. Klasa Binding ofron një veti XPath në të cilën mund të nënvizoni çdo pyetje XPath të mbështetur nga metoda XmlNode.SelectNodes. Të brendshmet e WPF përdorin këtë metodë për të ekzekutuar pyetjet e XPath. Mjerisht, kjo do të thotë se meqenëse XmlNode.SelectNodes nuk e mbështet aktualisht përdorimin e funksioneve XPath, as lidhjen e të dhënave WPF.

    Kutia e kombinuar e klientit dhe lista e porosive lidhen me grupin rezultues të nyjeve të pyetjeve XPath që kërkohen nga DataContext i elementit rrënjë Grid (tabela). Lista DataContext do të kthejë automatikisht CurrentItem të pamjes së koleksionit, i cili është një mbështjellës për koleksionin XmlNodes që është krijuar për tabelën DataContext. Me fjalë të tjera, DataContext i listës është klienti i përzgjedhur aktualisht. Për shkak se ItemsSource i listës është i lidhur në mënyrë implicite me DataContext-in e vet (sepse nuk u specifikua asnjë burim tjetër) dhe lidhja e ItemsSource ekzekuton një pyetje XPath për të marrë artikujt nga DataContext, atëherë ItemsSource në fakt lidhet me listën e porosive të klientit të zgjedhur.

    Mos harroni se kur lidheni me të dhënat XML, lidhja aktuale është me objektet e krijuara nga thirrja në XmlNode.SelectNodes. Pa dashje, mund të përfundoni me kontrolle të shumta që lidhen me grupe logjikisht ekuivalente, por fizikisht të ndryshme të XmlNodes. Kjo ndodh sepse çdo thirrje në XmlNode.SelectNodes krijon një grup të ri nyjesh XmlNode, edhe nëse kaloni të njëjtin pyetje XPath tek e njëjta XmlNode çdo herë. Ky është një problem i veçantë me lidhjen e të dhënave XML dhe mund të injorohet në mënyrë të sigurt kur lidhet me objektet e biznesit.

    Përdorimi i kontrolleve të shumta për të shfaqur objektet e biznesit

    Tani, supozoni se dëshironi të lidheni me të dhënat nga shembulli i mëparshëm, por të dhënat ekzistojnë si objekte biznesi dhe jo në XML. Si e ndryshon kjo mënyrën se si lidheni me nivele të ndryshme të hierarkisë së të dhënave? Sa e ngjashme apo e ndryshme do të jetë pritja?

    Në kodin në Fig. Figura 7 tregon klasat e thjeshta të përdorura për të krijuar objekte biznesi që ruajnë të dhëna për t'u lidhur. Këto klasa formojnë të njëjtën skemë logjike si të dhënat XML të përdorura në seksionin e mëparshëm.

    Oriz. 7. Klasa për krijimin e një hierarkie të objekteve të biznesit

    Klient i klasit publik
    {
    Emri i vargut publik (merr; vendos;)
    Lista publike Porositë (merr; vendos;)


    {
    ktheje këtë.Emri;
    }
    }

    Urdhri i klasës publike
    {
    vargu publik Desc (merr; vendos;)
    Lista publike Detajet e porosisë (merr; vendos;)

    vargun e anulimit publik ToString ()
    {
    ktheje këtë.Përshkruani;
    }
    }

    klasë publike OrderDetail
    {
    Produkt i vargut publik (merr; vendos;)
    publik int Sasia (merr; vendos;)
    }

    Kodi XAML për dritaren që shfaq këto objekte është paraqitur në Fig. 8. Është shumë i ngjashëm me XAML në Fig. 6, por ka dallime të rëndësishme midis tyre që ia vlen t'u kushtohet vëmendje. Ajo që XAML nuk sheh është konstruktori i dritares që krijon objektet e të dhënave dhe vendos DataContext në vend që të vendosë që XAML ta referojë atë si një burim. Vini re se asnjë nga kontrollet nuk e ka vetitë e tyre DataContext të vendosur drejtpërdrejt. Ata të gjithë trashëgojnë të njëjtën pronë DataContext, e cila është një shembull List .

    Oriz. 8. XAML për të lidhur objektet hierarkike të biznesit me ndërfaqen e përdoruesit








    />
    IsSynchronizedWithCurrentItem = "E vërtetë"
    ItemsSource = "(Rruga lidhëse =.)"
    />




    IsSynchronizedWithCurrentItem = "E vërtetë"
    ItemsSource = "(Rruga lidhëse = CurrentItem.Orders)"
    />



    Tekst = "Detajet e porosisë" />
    ItemsSource = "(Rruga lidhëse = CurrentItem.Orders.CurrentItem.
    Detajet e porosisë) "
    >



    Produkt:

    (

    )





    Një ndryshim tjetër domethënës kur lidhni me objektet e biznesit në vend të XML është se ItemsControl që pret informacionin e porosisë nuk ka nevojë të lidhet me SelectedItem të listës së porosive. Kjo qasje ishte e nevojshme në rastin e lidhjes XML sepse nuk ka asnjë mënyrë universale për t'iu referuar artikullit aktual të listës, artikujt e të cilit vijnë nga një pyetje lokale e XPath.

    Kur lidheni me objektet e biznesit në vend të XML, lidhja me nivelet e mbivendosura të elementeve të zgjedhur është e parëndësishme. Lidhja ItemsSource e ItemsControl përfiton nga kjo lehtësi duke specifikuar CurrentItem dy herë në shtegun e lidhjes: një herë për klientin e zgjedhur dhe një herë për porosinë e zgjedhur. Vetia CurrentItem është një anëtar i ICollectionView themelor, i cili është mbështjellësi rreth burimit të të dhënave, siç u diskutua më sipër.

    Ekziston një pikë tjetër interesante që lidhet me ndryshimin në mënyrën se si funksionon XML dhe objekti i biznesit. Meqenëse kampioni XML lidhet me XmlElements, ju duhet të siguroni shabllone DataTemplate për të shpjeguar se si të jepni klientët dhe porositë. Kur lidhni me objekte të personalizuara të biznesit, mund ta shmangni këtë punë shtesë thjesht duke anashkaluar metodën ToString të klasave Customer and Order dhe duke e lënë WPF të shfaqë daljen e asaj metode për objektet e dhëna. Ky fokus është i mjaftueshëm vetëm për objektet që mund të kenë paraqitje të thjeshta tekstuale. Kur punoni me objekte komplekse të të dhënave, ky truk i dobishëm mund të mos ketë kuptim.

    Një kontroll për të shfaqur të gjithë hierarkinë

    Deri më tani, vetëm mënyrat e shfaqjes së të dhënave hierarkike janë treguar duke treguar çdo nivel të hierarkisë në kontrolle të veçanta. Shpesh është e dobishme dhe e nevojshme të demonstrohen të gjitha nivelet e një strukture të dhënash hierarkike në një kontroll të vetëm. Një shembull kanonik i kësaj qasjeje është kontrolli TreeView, i cili mbështet shfaqjen dhe përsëritjen mbi një numër arbitrar nivelesh të të dhënave të ndërlidhura.

    Ka dy mënyra për të mbushur një WPF TreeView me artikuj. E para është shtimi manual i elementeve në kod ose XAML, dhe i dyti është krijimi i tyre përmes lidhjes së të dhënave.

    XAML e mëposhtme tregon se si mund të shtoni TreeViewItems në një TreeView në XAML:







    Qasja manuale e krijimit të artikujve në një TreeView ka kuptim në situatat kur kontrolli do të shfaqë gjithmonë një grup të vogël dhe statik artikujsh. Kur ju duhet të shfaqni sasi të mëdha të dhënash që mund të ndryshojnë me kalimin e kohës, një qasje më dinamike bëhet e nevojshme. Ka dy opsione në këtë fazë. Mund të shkruani kod që kalon nëpër strukturën e të dhënave, krijon TreeViewItems bazuar në objektet e të dhënave që gjen dhe i shton ato artikuj në TreeView. Përndryshe, ju mund të përfitoni nga shabllonet hierarkike të të dhënave dhe t'ia lini të gjithë punën WPF-së.

    Përdorimi i shablloneve të të dhënave hierarkike

    Mënyra se si WPF duhet t'i japë të dhënat hierarkike përmes shablloneve të të dhënave hierarkike mund të shprehet në mënyrë deklarative. Klasa HierarchicalDataTemplate është një mjet që lidh hendekun midis një strukture komplekse të të dhënave dhe një paraqitje vizuale të atyre të dhënave. Është shumë i ngjashëm me një DataTemplate normal, por ju lejon gjithashtu të specifikoni se nga e kanë origjinën fëmijët e një objekti të dhënash. Ju gjithashtu mund t'i siguroni klasës HierarchicalDataTemplate një shabllon për paraqitjen e këtyre fëmijëve.

    Supozoni se tani dëshironi të shfaqni të dhënat e paraqitura në Fig. 7 brenda një kontrolli TreeView. TreeView që rezulton mund të duket diçka si ajo e paraqitur në Fig. 9. Zbatimi i kësaj përfshin përdorimin e dy HierarchicalDataTemplate dhe një DataTemplate.

    Oriz. 9. Shfaqja e të gjithë hierarkisë së të dhënave në një TreeView

    Dy shabllone hierarkike shfaqin objektet e klientit dhe porosisë. Meqenëse objektet OrderDetail nuk kanë fëmijë, ato mund të jepen duke përdorur një DataTemplate johierarkike. Vetia ItemTemplate e TreeView përdor një shabllon për objektet e tipit Customer sepse objektet e klientit dhe objektet e të dhënave përmbahen në nivelin rrënjësor të TreeView. XAML i paraqitur në Fig. 10 tregon se si janë mbledhur të gjitha pjesët e kësaj enigme.

    Oriz. 10. Kodi XAML prapa ekranit TreeView




    xmlns: local = "clr-namespace: VariousBindingExamples"
    ObjectType = "(x: Lloji lokal: Klient)"
    MethodName = "Krijo klientë"
    />





    Produkt:

    (

    )


    x: Key = "Order Template"
    ItemsSource = "(Rruga lidhëse = Detajet e porosisë)"
    ItemTemplate = "(StaticResource OrderDetailTemplate)"
    >


    x: Çelësi = "Modeli i klientit"
    ItemsSource = "(Rruga lidhëse = Urdhërat)"
    ItemTemplate = "(StaticResource OrderTemplate)"
    >


    ItemsSource = "(Rruga lidhëse =.)"
    ItemTemplate = "(StaticResource CustomerTemplate)"
    />

    Unë jam duke ndarë një koleksion të objekteve të klientit në një tabelë DataContext (Grid) që përmban një TreeView. Në XAML, mund ta bëni këtë duke përdorur ObjectDataProvider, i cili është një mënyrë e përshtatshme për të thirrur një metodë nga XAML. Për shkak se DataContext trashëgohet në pemën e artikullit, DataContext i TreeView i referohet këtij grupi objektesh të klientit. Është për këtë arsye që ne mund t'i japim vetinë e saj ItemsSource një lidhje "(Binding Path =.)", e cila është një mënyrë për të treguar se vetia ItemsSource është e lidhur me DataContext e TreeView.

    Nëse veçorisë ItemTemplate të TreeView nuk i është caktuar një vlerë, atëherë TreeView do të shfaqë vetëm objektet e klientit të nivelit të lartë. Meqenëse WPF nuk di se si të japë një klient, ai do të thërrasë ToString për secilin klient dhe do të shfaqë këtë tekst për secilin artikull. Ai nuk do të jetë në gjendje të kuptojë se çdo klient ka një listë të objekteve të porosisë të lidhur me të dhe çdo objekt Porosi ka një listë të objekteve OrderDetail. Për shkak se WPF nuk mund të kuptojë në mënyrë magjike një skemë ekzistuese të të dhënave, ju duhet t'ia shpjegoni atë skemë WPF-së, në mënyrë që të mund ta përshkruajë saktë strukturën e të dhënave.

    Modelet HierarchicalDataTemplate hyjnë në lojë kur ju duhet të shpjegoni strukturën dhe pamjen e të dhënave në WPF. Modelet e përdorura në këtë demonstrim përmbajnë pemë vizuale shumë të thjeshta, në thelb vetëm fusha TextBlock me pak tekst në to. Në aplikacionet më të sofistikuara, shabllonet mund të kenë modele 3D ndërvepruese, rrotulluese, imazhe, grafikë vektoriale, UserControls komplekse ose çdo përmbajtje tjetër WPF të krijuar për të dhënë objektin themelor të të dhënave.

    Është e rëndësishme t'i kushtohet vëmendje rendit në të cilin janë deklaruar shabllonet. Një shabllon duhet të deklarohet përpara se të mund të referohet përmes një shprehjeje StaticResource. Kjo është një kërkesë e vendosur nga lexuesi XAML dhe vlen për të gjitha burimet, jo vetëm për shabllonet.

    Në vend të kësaj, ju mund t'i referoheni shablloneve duke përdorur një shprehje DynamicResource - në këtë rast rendi leksikor i deklaratave të shablloneve nuk është i rëndësishëm. Sidoqoftë, përdorimi i referencave DynamicResource, në krahasim me përdorimin e referencave të StaticResource, vjen me disa shpenzime ekzekutimi sepse ato gjurmojnë ndryshimet në sistemin e burimeve. Meqenëse ne nuk i tejkalojmë shabllonet në kohën e ekzekutimit, kjo kosto është e panevojshme, kështu që është më mirë të përdorni referencat e StaticResource dhe të rregulloni deklaratat e shablloneve në rendin e duhur.

    Puna me hyrjen e përdoruesit

    Për shumicën e programeve, shfaqja e të dhënave është vetëm gjysma e betejës. Analizimi, pranimi dhe refuzimi i të dhënave të përdoruesit është një tjetër sfidë e madhe. Në një botë ideale ku të gjithë përdoruesit gjithmonë futin të dhëna logjike dhe të sakta, kjo do të ishte një detyrë e lehtë. Por në botën reale, nuk është kështu. Përdoruesit e vërtetë bëjnë gabime shtypi, harrojnë të fusin vlera, futin vlera në vendet e gabuara, fshijnë hyrjet që nuk duhen fshirë, shtojnë hyrje që nuk duhen shtuar dhe përgjithësisht ndjekin ligjet e Murphy kudo që është e mundur.

    Është përgjegjësia jonë si zhvillues dhe arkitektë për të luftuar atë që përdoruesit hyjnë në mënyrë të pashmangshme gabimisht ose keqdashje. Korniza detyruese WPF mbështet vërtetimin e hyrjes. Në seksionet e ardhshme të këtij artikulli, unë do të shpjegoj se si të përdorni mbështetjen e vërtetimit të WPF dhe si t'i shfaqni përdoruesit mesazhe në lidhje me gabimet e vërtetimit.

    Vleresimi i hyrjes nëpërmjet ValidationRules

    Versioni i parë i WPF, i cili ishte pjesë e Microsoft® .NET Framework 3.0, kishte vetëm mbështetje të kufizuar të vlefshmërisë së hyrjes. Klasa Binding kishte një veti ValidationRules që mund të mbante çdo numër klasash të prejardhura nga ValidationRule. Secila prej këtyre rregullave mund të përmbajë një logjikë që kontrollon nëse vlera e kufizuar është e vlefshme.

    Në atë kohë, WPF kishte vetëm një nënklasë të ValidationRule të quajtur ExceptionValidationRule. Zhvilluesit mund ta shtojnë këtë rregull në veçorinë ValidationRules të lidhjes, dhe më pas ai do të kapte përjashtimet e hedhura gjatë përditësimeve të burimit të të dhënave, duke lejuar ndërfaqen e përdoruesit të shfaqë një mesazh gabimi përjashtimi. Dobia e kësaj qasjeje për vërtetimin e të dhënave është e diskutueshme duke pasur parasysh se themeli i përvojës së mirë të përdoruesit është parandalimi i shfaqjes së detajeve të panevojshme teknike për ta. Mesazhet e gabimit në përjashtimet e analizës së të dhënave janë zakonisht një detaj i tillë për shumicën e përdoruesve, por përsëri në temën tonë.

    Supozoni se kemi një klasë që përfaqëson një epokë në kohë, siç është klasa e thjeshtë Era e paraqitur këtu:

    Epoka e klasës publike
    {

    }

    Nëse dëshironi të lejoni përdoruesin të ndryshojë datën e fillimit dhe kohëzgjatjen e një epoke, mund të përdorni dy kontrolle të kutisë së tekstit dhe të lidhni vetitë e tyre të tekstit me vetitë e shembullit Era. Meqenëse përdoruesi mund të fusë çfarëdo që dëshiron në kutinë e tekstit, nuk ka asnjë mënyrë për t'u siguruar që teksti i futur do të konvertohet në një shembull DateTime ose TimeSpan. Në këtë rast, mund të përdorni ExceptionValidationRule për të raportuar gabime në transformimin e të dhënave dhe më pas t'i shfaqni ato gabime në ndërfaqen e përdoruesit. XAML i paraqitur në Fig. 11 tregon se si mund të realizohet kjo detyrë.

    Oriz. 11. Klasa e thjeshtë që përfaqëson epokën e kohës


    Data e fillimit:









    Kohëzgjatja:
    Grid.Row = "3"
    Teksti = "(Lidhje
    Rruga = Kohëzgjatja,

    />

    Këto dy kuti teksti demonstrojnë dy mënyra në të cilat ExceptionValidationRule mund të shtohet në vetinë ValidationRules të një lidhjeje në XAML. Kutia e tekstit "Data e fillimit" përdor sintaksën e zgjeruar të elementit të vetive për të shtuar rregullin drejtpërdrejt. Kutia e tekstit Kohëzgjatja përdor një sintaksë stenografike që thjesht e cakton pronën lidhëse ValidatesOnExceptions në true. Të dy lidhjet kanë veçorinë UpdateSourceTrigger të caktuar në PropertyChanged në mënyrë që hyrja të vërtetohet sa herë që veçorisë Text i jepet një vlerë e re, në vend që të presim që kontrolli të humbasë fokusin. Një pamje nga ekrani i programit është paraqitur në Fig. 12.

    Oriz. 12. ExceptionValidationRule shfaq gabimet e vërtetimit

    Shfaqja e gabimeve të vërtetimit

    Siç tregohet në Fig. 13, kutia e tekstit Kohëzgjatja përmban një vlerë të pavlefshme. Vargu që ai përmban nuk është i konvertueshëm në një shembull TimeSpan. Mesazhi kërcyes i kutisë së tekstit shfaq një mesazh gabimi dhe një ikonë e vogël e kuqe e gabimit shfaqet në anën e djathtë të kontrollit. Kjo sjellje nuk është automatike, por është e lehtë për t'u zbatuar dhe përshtatur.

    Oriz. 13. Vizualizimi i gabimeve të zbuluara gjatë verifikimit të hyrjes për përdoruesin




    DockPanel.Dock = "Djathtas"
    Marzhi = "2.0"
    ToolTip = "Përmban të dhëna të pavlefshme"
    Gjerësia = "10" Lartësia = "10"
    >











    Klasa Static Validation formon lidhjen midis kontrollit dhe çdo gabimi të vërtetimit që ai përmban duke përdorur vetitë e bashkangjitura dhe metodat statike. Këto veti të bashkangjitura mund të referohen në XAML për të krijuar një përshkrim të vetëm shënjimi se si ndërfaqja e përdoruesit duhet të paraqesë gabimet e hasura gjatë verifikimit të hyrjes tek përdoruesi. Kodi XAML në Fig. 13 është përgjegjës për shpjegimin se si të jepen mesazhet e gabimit të hyrjes për dy kontrollet e kutisë së tekstit nga shembulli i mëparshëm.

    Stili ("Stili") në Fig. 13 synon të gjitha rastet e kutisë së tekstit në ndërfaqen e përdoruesit Ai zbaton tre parametra në kutinë e tekstit. Së pari, Setter ndikon në vetinë Margin të kutisë së tekstit. Vetia Margin vendoset në një vlerë që ofron hapësirë ​​të mjaftueshme për të shfaqur ikonën e gabimit në anën e djathtë.

    Vetia tjetër Setter në Style vendos ControlTemplate që përdoret për të dhënë kutinë e tekstit kur përmban të dhëna të pavlefshme. Ai vendos veçorinë e bashkangjitur Validation.ErrorTemplate në ControlTemplate të deklaruar mbi Style. Kur klasa Validation raporton se vlefshmëria ka zbuluar një ose më shumë gabime në kutinë e tekstit, kutia e tekstit e jep mesazhin duke përdorur këtë shabllon. Kjo është ajo që krijon ikonën e kuqe të gabimit të paraqitur në Fig. 12.

    Stili përmban gjithashtu një Këmbëz që mban gjurmët e vetive Validation.HasError të bashkangjitur në fushën e tekstit. Kur klasa Validation cakton tiparin e bashkangjitur HasError në true për një fushë teksti të veçantë, aktivizimi i "Kyçja në stil" ndizet dhe vendos mesazhin që shfaqet në fushën e tekstit. Përmbajtja e mesazhit pop-up lidhet me mesazhin e gabimit të një përjashtimi të hedhur kur përpiqeni të konvertoni tekstin nga një fushë teksti në një shembull të llojit të të dhënave të vetive të burimit të të dhënave.

    Po verifikon hyrjen nëpërmjet IDataErrorInfo

    Me prezantimin e Microsoft .NET Framework 3.5, mbështetja e vërtetimit të hyrjeve të WPF-së është përmirësuar në mënyrë dramatike. Qasja ValidationRule është e dobishme për aplikacione të thjeshta, por aplikacionet reale merren me gjithë kompleksitetin e të dhënave reale dhe rregullave të biznesit. Kodimi i rregullave të biznesit në objektet ValidationRule jo vetëm që e lidh këtë kod me platformën WPF, por gjithashtu parandalon që logjika e biznesit të jetë aty ku duhet: në objektet e biznesit!

    Shumë aplikacione kanë një shtresë biznesi ku kompleksiteti i përpunimit të rregullave të biznesit është i përmbledhur në një grup objektesh biznesi. Kur përpilohet me Microsoft .NET Framework 3.5, ju mund të përdorni ndërfaqen IDataErrorInfo për të detyruar WPF të pyesë objektet e biznesit nëse ato janë në një gjendje të vlefshme apo jo. Kjo eliminon nevojën për të vendosur logjikën e biznesit në objekte të ndara nga shtresa e biznesit dhe ju lejon të krijoni objekte biznesi që janë platformë të pavarura nga ndërfaqja e përdoruesit. Meqenëse ndërfaqja IDataErrorInfo ka ekzistuar prej disa vitesh, ajo gjithashtu e bën më të lehtë ripërdorimin e objekteve të biznesit nga Windows Forms ose aplikacionet ASP.NET të trashëguara.

    Supozoni se dëshironi të siguroni vërtetimin për një epokë që shkon përtej thjesht bërjes së hyrjes së përdoruesit të konvertueshme në llojin e të dhënave të një veçorie të burimit të të dhënave. Mund të ketë kuptim të mos vendosim datën e fillimit të një epoke në të ardhmen, pasi nuk dimë për epokat që janë përpara. Mund të ketë gjithashtu kuptim të kërkohet që një epokë të jetë të paktën një milisekondë.

    Këto lloje rregullash janë të ngjashme me idenë e përgjithshme të logjikës së biznesit në atë që të dyja janë shembuj të rregullave të fushëveprimit. Rregullat e fushëveprimit krijohen më së miri në objektet që ruajnë gjendjen e tyre: objektet e fushës. Në kodin e treguar në Fig. 14, shfaqet një klasë SmartEra që ekspozon mesazhet e gabimit të vlefshmërisë përmes ndërfaqes IDataErrorInfo.

    Oriz. 14. IDataErrorInfo ofron mesazhe në lidhje me gabimet e identifikuara nga vërtetimi

    Klasa publike SmartEra
    : System.ComponentModel.IDataErrorInfo
    {
    publike DataTime Data e fillimit (merr; vendos;)
    Kohëzgjatja publike publike (merr; vendos;)

    #region IDataErrorInfo Anëtarët

    Gabim i vargut publik
    {
    marr (ktheje null;)
    }

    varg publik kjo
    {
    marr
    {
    varg msg = null;
    ndërprerës (pronësi)
    {
    rasti "Data e fillimit":
    nëse (DataKoha. Tani< this.StartDate)
    msg = "Data e fillimit duhet të jetë në të kaluarën.";
    pushim;

    rasti "Kohëzgjatja":
    nëse (kjo. Kohëzgjatja. Rritjet == 0)
    msg = "Një epokë duhet të ketë një kohëzgjatje.";
    pushim;

    default:
    hedh Argumentin e riPërjashtim (
    "Pronë e panjohur:" + pronë);
    }
    kthe mesazhin;
    }
    }

    #endregion // Anëtarët IDataErrorInfo
    }

    Është shumë e lehtë të konsumosh mbështetjen e vlefshmërisë së klasës SmartEra nga ndërfaqja e përdoruesit WPF. E tëra çfarë ju duhet të bëni është t'i tregoni lidhjeve që temat duhet të pranojnë ndërfaqen IDataErrorInfo në objektin me të cilin janë të lidhura. Kjo mund të bëhet në një nga dy mënyrat, siç tregohet në Fig. 15.

    Oriz. 15. Përdorimi i logjikës së vlefshmërisë


    Data e fillimit:










    Kohëzgjatja:
    Grid.Row = "3"
    Teksti = "(Lidhje
    Rruga = Kohëzgjatja,
    UpdateSourceTrigger = PropertyChanged,
    ValidatesOnDataErrors = E vërtetë,
    ValidatesOnExceptions = E vërtetë) "
    />

    Në mënyrë të ngjashme, mund të shtoni një ExceptionValidationRule në ValidationRules të lidhjes në mënyrë eksplicite ose të nënkuptuar, mund të shtoni një DataErrorValidationRule drejtpërdrejt në ValidationRules të një lidhjeje, ose mund ta vendosni vetinë ValidatesOnDataErrors në true. Të dyja qasjet kanë të njëjtin efekt përfundimtar - sistemi i detyrueshëm kërkon ndërfaqen IDataErrorInfo të burimit të të dhënave për gabimet e identifikuara nga vërtetimi.

    Duke përmbledhur

    Për një arsye, shumë zhvillues thonë se veçoria e tyre e preferuar e WPF është mbështetja e saj e gjerë e lidhjes së të dhënave. Lidhjet në WPF janë aq të fuqishme dhe të përhapura saqë kërkojnë që shumë zhvillues softuerësh të rregullojnë kuptimin e tyre për marrëdhënien midis të dhënave dhe ndërfaqes së përdoruesit. Shumë nga përbërësit kryesorë të WPF punojnë së bashku për të mbështetur rastet komplekse të lidhjes së të dhënave, siç janë shabllonet, stilet dhe vetitë e bashkangjitura.

    Me një numër relativisht të vogël linjash të XAML, ju mund të shprehni synimet tuaja për shfaqjen e një strukture hierarkike të të dhënave dhe vërtetimin e hyrjes së përdoruesit. Në situata më komplekse, mund të përfitoni plotësisht nga sistemi i lidhjes duke e aksesuar atë në mënyrë programore. Me një infrastrukturë kaq të fuqishme në dispozicion të tyre, zhvilluesit që ndërtojnë aplikacione moderne të biznesit mund t'i afrohen më në fund qëllimit të tyre të vjetër për të ofruar një përvojë të shkëlqyer të përdoruesit dhe vizualizime bindëse të të dhënave.

    Përditësimi i fundit: 7.02.2016

    Në WPF, binding është një mjet i fuqishëm programimi pa të cilin asnjë aplikacion serioz nuk mund të bëjë.

    Lidhja përfshin ndërveprimin e dy objekteve: një burim dhe një destinacion. Objekti i destinacionit lidhet me një veti specifike të objektit burim. Nëse objekti burim modifikohet, objekti i destinacionit gjithashtu do të modifikohet. Për shembull, forma më e thjeshtë duke përdorur një spirancë:

    Një shprehje si kjo përdoret për të përcaktuar lidhjen:

    (Emri i elementit lidhës = Emri_burimi_objekti, shtegu = prona_burimi_objekti)

    Kjo do të thotë, në këtë rast, elementi ynë TextBox është burimi, dhe TextBlock është marrësi lidhës. Vetia Text e TextBlock është e lidhur me veçorinë Text të TextBox. Si rezultat, kur futni në një fushë teksti, ndryshimet në bllokun e tekstit do të ndodhin në mënyrë sinkrone.

    Puna me lidhjen në C #

    Objekti kryesor gjatë krijimit të një lidhjeje është objekti System.Windows.Data.Binding. Duke përdorur këtë objekt, ne mund të marrim lidhjen ekzistuese për elementin:

    Lidhja e lidhjes = BindingOperations.GetBinding (myTextBlock, TextBlock.TextProperty);

    Në këtë rast, marrim lidhjen për vetinë e varësisë TextProperty të elementit myTextBlock.

    Është gjithashtu e mundur të vendosni plotësisht lidhjen në kodin C #:

    Dritarja kryesore publike () (InitializeComponent (); Lidhja lidhëse = Lidhja e re (); binding.ElementName = "myTextBox"; // lidhja e elementit të burimit. Path = PropertyPath i ri ("Text"); // vetia e elementit burim myTextBlock. SetBinding ( TextBlock.TextProperty, lidhëse); // vendosja e lidhjes për elementin marrës)

    Nëse në të ardhmen nuk kemi më nevojë për lidhje, atëherë mund të përdorim klasën BindingOperations dhe metodat e saj ClearBinding () (heq një lidhje) dhe ClearAllBindings () (heq të gjitha lidhjet për këtë element)

    BindingOperations.ClearBinding (myTextBlock, TextBlock.TextProperty);

    BindingOperations.ClearAllBindings (myTextBlock);

    Disa veti të klasës Binding:

      Emri i elementit: emri i elementit për t'u lidhur

      IsAsync: nëse vendoset në True, ai përdor mënyrën asinkrone të marrjes së të dhënave nga objekti. Parazgjedhja është False

      Modaliteti: modaliteti i lidhjes

      TargetNullValue: Vendos vlerën e paracaktuar nëse vetia e lidhur e burimit lidhës është null

      RelativeSource: krijon një lidhje në lidhje me objektin aktual

      Burimi: tregon objektin burimor nëse nuk është kontroll.

      XPath: përdoret në vend të veçorisë së rrugës për të specifikuar shtegun drejt të dhënave xml

    Modalitetet e kapjes

    Vetia Mode e një objekti Binding, e cila përfaqëson mënyrën e lidhjes, mund të marrë vlerat e mëposhtme:

      OneWay: Vetia e objektit të destinacionit ndryshohet pasi të jetë modifikuar vetia e objektit burimor.

      OneTime: Vetia e objektit të destinacionit vendoset në vetinë e objektit burim vetëm një herë. Ndryshimet e mëtejshme në burim nuk ndikojnë në objektin e destinacionit në asnjë mënyrë.

      TwoWay: Si Aplikacioni ashtu edhe Burimi mund të modifikojnë vetitë e lidhura të njëri-tjetrit.

      OneWayToSource: Objekti i destinacionit në të cilin deklarohet lidhja ndryshon objektin burimor.

      Default: sipas parazgjedhjes (nëse vetia TextBox.Text ndryshon, atëherë ajo ka vlerën TwoWay, në raste të tjera OneWay).

    Aplikimi i modalitetit Snap:

    Përditësimi i lidhjes. UpdateSourceTrigger

    Lidhja njëkahëshe nga burimi në destinacion ndryshon vetitë e destinacionit pothuajse menjëherë. Por nëse përdorim lidhjen e dyanshme në rastin e fushave të tekstit (si në shembullin e mësipërm), atëherë kur ndryshon destinacioni, vetia e burimit nuk ndryshon menjëherë. Pra, në shembullin e mësipërm, në mënyrë që fusha e tekstit burim të ndryshojë, duhet të transferojmë fokusin nga fusha e tekstit të destinacionit. Dhe në këtë rast, vetia UpdateSourceTrigger e klasës Binding hyn në lojë, e cila përcakton se si do të ndodhë përditësimi. Kjo veti merr një nga vlerat e numërimit të UpdateSourceTrigger:

      PropertyChanged: Burimi i lidhjes përditësohet sapo prona përditësohet në marrës

      LostFocus: Burimi i ankorimit përditësohet vetëm pasi marrësi humbet fokusin

      E qartë: Burimi nuk përditësohet derisa të thirret metoda BindingExpression.UpdateSource ()

      Default: vlera e paracaktuar. Për shumicën e pronave, kjo është vlera PropertyChanged. Dhe për veçorinë Text të elementit TextBox, kjo është vlera LostFocus

    Në këtë rast, ne po flasim për përditësimin e burimit të lidhjes pas ndryshimit të lavamanit në modalitetet OneWayToSource ose TwoWay. Kjo do të thotë, në mënyrë që të kemi të dyja fushat e tekstit të lidhura nga modaliteti TwoWay për t'u përditësuar menjëherë pas ndryshimit të njërës prej tyre, duhet të përdorim vlerën UpdateSourceTrigger.PropertyChanged:

    Veti burimore

    Vetia Source ju lejon të lidheni edhe me objekte që nuk janë kontrolle WPF. Për shembull, le të përcaktojmë një klasë Phone:

    Telefoni i klasës (vargu publik Titulli (merr; vendos;) varg publik Kompania (merr; vendos;) publik int Çmimi (merr; vendos;))

    Tani le të krijojmë një objekt të kësaj klase dhe të përcaktojmë një lidhje me të:

    Vetia TargetNullValue

    Në rast se një veti në burimin e lidhjes është papritmas null, domethënë nuk është vendosur, ne mund të vendosim një vlerë të paracaktuar. Për shembull:

    Në këtë rast, burimi nexusPhone nuk ka grupin e vetive Title, kështu që blloku i tekstit do të shfaqë vlerën e paracaktuar të specifikuar në parametrin TargetNullValue.

    Prona RelativeSource

    Vetia RelativeSource ju lejon të vendosni një lidhje në lidhje me elementin burim, i cili ka një lloj marrëdhënieje me elementin destinues. Për shembull, një element burimor mund të jetë një nga kontejnerët e jashtëm për një element destinacion. Ose burimi dhe destinacioni mund të jenë i njëjti artikull.

    Për të vendosur këtë veti, përdoret objekti RelativeSource me të njëjtin emër. Ky objekt ka një veçori Mode që specifikon metodën e lidhjes. Ai merr një nga vlerat e numërimit të RelativeSourceMode:

      Vetë: lidhja kryhet me një veti të të njëjtit element. Domethënë, elementi burimor i lidhjes është në të njëjtën kohë destinacioni i lidhjes.

      FindAncestor: Lidhet me një veti të një elementi kontejner.

    Për shembull, lidhjet e burimit dhe destinacionit janë të pajtueshme në vetë elementin:

    Këtu, teksti dhe ngjyra e sfondit të kutisë së tekstit janë të lidhura nga një spirancë e dyanshme. Si rezultat, ne mund të shohim vlerën numerike të ngjyrës në fushë, ta ndryshojmë atë dhe sfondi i fushës do të ndryshojë me të.

    Lidhja me vetitë e kontejnerit:

    Kur përdorni modalitetin FindAncestor, domethënë lidhjen me një kontejner, duhet gjithashtu të specifikoni parametrin AncestorType dhe t'i kaloni atij llojin e kontejnerit si shprehje AncestorType = (x: Type Container-element_type). Në këtë rast, si kontejner, mund të zgjidhnim çdo kontenier në pemën e elementeve, në veçanti, në këtë rast, përveç Gridit, një enë e tillë është edhe elementi Window.

    Vetia e DataContext

    Objekti FrameworkElement që kontrollon trashëgim ka një veti interesante DataContext. Kjo ju lejon të vendosni disa kontekste të dhënash për një element dhe elementët e tij të mbivendosur. Elementet e mbivendosur më pas mund të përdorin objektin Binding për t'u lidhur me vetitë specifike të atij konteksti. Për shembull, le të përdorim klasën e përcaktuar më parë Phone dhe të krijojmë një kontekst të dhënash nga një objekt i kësaj klase:

    Kështu, ne vendosëm veçorinë DataContext në një burim dinamik ose statik. Pastaj ne lidhemi me këtë burim.

    Artikujt kryesorë të lidhur