Επεκτάσεις σύνδεσης και σήμανσης xaml χρησιμοποιώντας την τοπική προσαρμογή ως παράδειγμα. Ρύθμιση εμφάνισης δεδομένων με σύνδεση δεδομένων και WPF

  • Προγραμματισμός
  • Ένα από τα βασικά σημεία στην ανάπτυξη xamlΟι προσανατολισμένες εφαρμογές είναι να χρησιμοποιούν δεσμεύσεις ( Δεσίματα). Δεσμευτικός- Αυτό μεσολαβητής(ενδιάμεσος), με τη βοήθεια του οποίου οι τιμές των ιδιοτήτων συγχρονίζονται μεταξύ των σχετικών αντικειμένων.

    Αξίζει να σημειωθεί ότι δεν είναι προφανές, αλλά σημαντική απόχρωση: Αν και το δέσιμο παραπέμπει κατά κάποιο τρόπο στα αλληλεπιδρώντα αντικείμενα, δεν τα εμποδίζει να συλλέγονται σκουπίδια!

    Κληρονομιά από μια τάξη Δεσμευτικόςεπιτρέπεται, αλλά για λόγους ασφαλείας κώδικα που υπερισχύουν της μεθόδου ProvideValue, που σχετίζεται με την κύρια λογική λειτουργίας, δεν επιτρέπεται. Αυτό προκαλεί κατά κάποιο τρόπο τους προγραμματιστές να χρησιμοποιήσουν το μοτίβο Μετατροπέας, το οποίο είναι στενά συνυφασμένο με το θέμα των δεσίμων.

    Τα δεσίματα είναι ένα πολύ ισχυρό εργαλείο, αλλά σε ορισμένες περιπτώσεις η δήλωσή τους γίνεται περιεκτική και άβολη για τακτική χρήση, για παράδειγμα, για εντοπισμό. Σε αυτό το άρθρο θα δούμε μια απλή και κομψή μέθοδο που κάνει τον κώδικα πολύ πιο καθαρό και πιο όμορφο.


    Δηλώστε δεσμεύσεις σε xamlεπιτρέπεται με δύο τρόπους:



    Προφανώς, η πρώτη μέθοδος δεν φαίνεται πολύ συνοπτική, αλλά η δεύτερη, με βάση τη χρήση επεκτάσεις σήμανσης, χρησιμοποιείται πιο συχνά. Στην πλατφόρμα WPFυπάρχει η ευκαιρία να δημιουργήσουμε προσαρμοσμένες επεκτάσεις σήμανσης. Για παράδειγμα, είναι βολικά στη χρήση για εντοπισμό.


    Στην απλούστερη περίπτωση, πρέπει να κληρονομήσετε από την τάξη Επέκταση Markupκαι εφαρμόστε τη μέθοδο ProvideValue, στο οποίο μπορείτε να λάβετε την επιθυμητή τιμή χρησιμοποιώντας το κλειδί.

    Αλλά αυτή η υλοποίηση δεν υποστηρίζει καυτή βάρδιαγλώσσα κατά την εκτέλεση του προγράμματος. Για να γίνει αυτή η βελτίωση, είναι απαραίτητο, πρώτον, να αποθηκευτεί μια αναφορά στο τοπικό στοιχείο διεπαφής και, δεύτερον, το οποίο είναι λιγότερο προφανές, να υπάρχει με κάποιο τρόπο στην εφαρμογή μια αναφορά στην ίδια την παρουσία κλάσης Εντοπισμός, για την προστασία του από τη συλλογή σκουπιδιών και, τρίτον, απαιτείται η σωστή εφαρμογή της εγγραφής και της απεγγραφής από το συμβάν αλλαγής γλώσσας.

    Εάν κάνετε αυτά τα πράγματα λάθος, είναι εγγυημένο ότι θα έχετε διαρροές μνήμης εάν οι προβολές δημιουργηθούν και καταστραφούν δυναμικά ενώ εκτελείται η εφαρμογή, κάτι που συμβαίνει σε πολλές περιπτώσεις. Δηλαδή, προσθέτοντας ότι δεν φαίνεται το πιο πολύ σύνθετη λειτουργία, θα πρέπει να ασχοληθείτε με μη τετριμμένα θέματα αδύναμους κρίκουςΚαι αδύναμες συνδρομές εκδηλώσεων. Και ο κώδικας δεν θα είναι πολύ απλός.

    Επιπλέον, στις xaml-πλατφόρμες Windows Phone, Windows StoreΚαι Xamarin.Έντυπαδεν υπάρχει τρόπος δημιουργίας προσαρμοσμένων επεκτάσεων σήμανσης, που αναδεικνύει την ιδέα της χρήσης δεσμεύσεων ως επεκτάσεις σήμανσης

    Ας μην χτυπάμε γύρω από τον θάμνο, ορίστε τι χρειαζόμαστε:

    Δημόσια αφηρημένη κλάση BindingExtension: Binding, IValueConverter ( προστατευμένη BindingExtension() ( Source = Converter = this; ) προστατευμένη BindingExtension(πηγή αντικειμένου) // ορίστε την Source σε null για χρήση DataContext ( Source = source; Converter = this; ) protected BindingSextension(Relative relativeSource) ( RelativeSource = relativeSource; Converter = this; ) δημόσιο αφηρημένο αντικείμενο Μετατροπή (τιμή αντικειμένου, Τύπος targetType, παράμετρος αντικειμένου, πολιτισμός CultureInfo δημόσιου εικονικού αντικειμένου ConvertBack (τιμή αντικειμένου, Τύπος targetType, παράμετρος αντικειμένου, πολιτισμός CultureInfo) NotImplementedException();
    Αξίζει να σημειωθεί ότι το δέσιμο είναι ένας μετατροπέας για τον εαυτό του. Ως αποτέλεσμα, έχουμε συμπεριφορά παρόμοια με αυτήν της κληρονομιάς από μια τάξη Επέκταση Markup, αλλά, επιπλέον, Παραμένει δυνατή η χρήση τυπικών μηχανισμών ελέγχου αποκομιδής απορριμμάτων!

    Τώρα η λογική για την εμφάνιση τοπικής προσαρμογής δεν θα μπορούσε να είναι πιο απλή:

    Δημόσια μερική κλάση Localizing: Base.BindingExtension ( δημόσια στατική μόνο για ανάγνωση Manager ActiveManager = new Manager(); public Localizing() ( Source = ActiveManager; Path = new PropertyPath("Source"); ) public Localizing(κλειδί συμβολοσειράς) ( Key = key Πηγή = ActiveManager = new PropertyPath("Πηγή" δημόσιας συμβολοσειράς ( get; set; ) Convert(τιμή αντικειμένου, Τύπος targetType, παράμετρος αντικειμένου, CultureInfo Culture) (κλειδί var = Κλειδί). τιμή ως ResourceManager; var localizedValue = resourceManager == null || επιστροφή localizedValue.
    δημόσια μερική κλάση Localizing ( Public class Manager: INotifyPropertyChanged ( private ResourceManager _source; public ResourceManager Source ( get ( return _source; ) set ( _source = value; PropertyChanged(this, new PropertyChangedEventArgs("Source")); ) ) δημόσια συμβολοσειρά Get( κλειδί συμβολοσειράς, συμβολοσειρά stringFormat = null) ( if (_source == null || string.IsNullOrWhiteSpace(key)) κλειδί επιστροφής; var localizedValue = _source.GetString(key) ?? ":" + κλειδί + ":"; συμβολοσειρά επιστροφής .IsNullOrEmpty(stringFormat) ;
    Είναι εύκολο να προσθέσετε τη δυνατότητα αλλαγής πεζών-κεφαλαίων γραμμάτων:

    Δημόσια μερική κλάση Localizing: Base.BindingExtension ( δημόσιος αριθμός Περιπτώσεις ( Προεπιλογή, Κάτω, Άνω ) δημόσια στατική μόνο για ανάγνωση Manager ActiveManager = new Manager(); public Localizing() ( Source = ActiveManager; Path = new PropertyPath("Source"); ) δημόσιος εντοπισμός(κλειδί συμβολοσειράς) (Κλειδί = κλειδί; Πηγή = ActiveManager; Διαδρομή = νέο PropertyPath("Πηγή"); ) δημόσια συμβολοσειρά Κλειδί ( get; set; ) δημόσια περίπτωση Υπόθεση ( get; set; ) δημόσια συμβολοσειρά παράκαμψης ToString() ( επιστρέφει το Convert(ActiveManager.Source, null, Key, Thread.CurrentThread.CurrentCulture) ως συμβολοσειρά ?? string.Empty; ) δημόσια παράκαμψη αντικειμένου Convert(τιμή αντικειμένου, Τύπος targetType, παράμετρος αντικειμένου, πολιτισμός CultureInfo) ( κλειδί var = Κλειδί; var resourceManager = τιμή ως ResourceManager; var localizedValue = resourceManager == null || "); switch (Case) ( case Cases.Lower: return localizedValue.ToLower(); case Cases.Upper: return localizedValue.ToUpper();
    προεπιλογή: επιστροφή localizedValue. xaml) ))


    ΣΕ WPFΗ εγγραφή φαίνεται βολική και όμορφη, αλλά υπάρχουν ορισμένοι περιορισμοί των αναλυτών σήμανσης σε διάφορες πλατφόρμες: Για να απαλλαγούμε απόαπό το απαιτούμενο πρόθεμα m:πρέπει να τοποθετήσετε την επέκταση σήμανσης σε ξεχωριστή διάταξη και μέσα


    Ιδιότητες/AssemblyInfo.cs Windows Phoneκαθορίζει τις ακόλουθες οδηγίες: Για να προσαρμόσετε το όνομα του προθέματος σε:


    ή ΚατάστημαΧρήση επεκτάσεων σύνδεσης ( WPFΒασικές επεκτάσεις ) σε. δεν αποκλείει τις κανονικές επεκτάσεις σήμανσης, αλλά σε ορισμένες περιπτώσεις είναι ακόμη πιο ασφαλής και

    απλή επιλογή

    Επίσης, όλα αυτά δεν περιορίζονται μόνο στον εντοπισμό, αλλά είναι κατάλληλα για πολλούς άλλους σκοπούς...

    Στο WPF, το δεσμευτικό είναι ισχυρό εργαλείοπρογραμματισμού, χωρίς τον οποίο δεν μπορεί να κάνει καμία σοβαρή εφαρμογή.

    Η σύνδεση περιλαμβάνει την αλληλεπίδραση δύο αντικειμένων: μιας πηγής και ενός προορισμού. Το αντικείμενο προορισμού δημιουργεί μια σύνδεση σε μια συγκεκριμένη ιδιότητα του αντικειμένου προέλευσης. Εάν τροποποιηθεί το αντικείμενο προέλευσης, θα τροποποιηθεί και το αντικείμενο προορισμού. Για παράδειγμα, η απλούστερη μορφή που χρησιμοποιεί δέσμευση:

    Για να ορίσετε μια δέσμευση, μια έκφραση όπως:

    (Binding ElementName=Source object_name, Path=Source object_property)

    Δηλαδή, σε αυτήν την περίπτωση, το στοιχείο TextBox είναι η πηγή και το TextBlock είναι ο προορισμός της σύνδεσης. Ιδιοκτησία Κείμενο στοιχείουΤο TextBlock είναι δεσμευμένο στην ιδιότητα Text του στοιχείου TextBox. Ως αποτέλεσμα, όταν εισέρχεστε σε ένα πεδίο κειμένου, οι αλλαγές στο μπλοκ κειμένου θα πραγματοποιούνται συγχρονισμένα.

    Εργασία με Binding σε C#

    Το βασικό αντικείμενο κατά τη δημιουργία ενός δεσμευτικού είναι το αντικείμενο System.Windows.Data.Binding. Χρησιμοποιώντας αυτό το αντικείμενο μπορούμε να πάρουμε την ήδη υπάρχουσα σύνδεση για το στοιχείο:

    Binding binding = BindingOperations.GetBinding(myTextBlock, TextBlock.TextProperty);

    Σε αυτήν την περίπτωση, λαμβάνουμε μια σύνδεση για την ιδιότητα εξάρτησης TextProperty του στοιχείου myTextBlock.

    Μπορείτε επίσης να ορίσετε τη σύνδεση εξ ολοκλήρου σε κώδικα C#:

    Public MainWindow() ( InitializeComponent(); Binding binding = new Binding(); binding.ElementName = "myTextBox"; // στοιχείο πηγής binding.Path = new PropertyPath("Text"); // ιδιότητα στοιχείου πηγής myTextBlock. SetBinding( TextBlock.TextProperty, binding // ρύθμιση της σύνδεσης για το στοιχείο δέκτη)

    Εάν στο μέλλον δεν χρειαζόμαστε πλέον δέσμευση, μπορούμε να χρησιμοποιήσουμε την κλάση BindingOperations και τις μεθόδους της ClearBinding() (αφαιρεί ένα binding) και ClearAllBindings() (αφαιρεί όλες τις δεσμεύσεις για ένα δεδομένο στοιχείο).

    BindingOperations.ClearBinding(myTextBlock, TextBlock.TextProperty);

    BindingOperations.ClearAllBindings(myTextBlock);

    Μερικές ιδιότητες της κλάσης Binding:

      ElementName : το όνομα του στοιχείου στο οποίο δημιουργείται η σύνδεση

      IsAsync: Εάν οριστεί σε True, χρησιμοποιεί ασύγχρονη λειτουργία για τη λήψη δεδομένων από το αντικείμενο. Προεπιλογές σε False

      Λειτουργία: λειτουργία snap

      TargetNullValue: Ορίζει την προεπιλεγμένη τιμή εάν η δεσμευμένη ιδιότητα της πηγής δέσμευσης είναι null

      RelativeSource: Δημιουργεί μια σύνδεση σε σχέση με το τρέχον αντικείμενο

      Source : Υποδεικνύει το αντικείμενο προέλευσης εάν δεν είναι στοιχείο ελέγχου.

      XPath : χρησιμοποιείται αντί για την ιδιότητα διαδρομής για τον καθορισμό της διαδρομής προς τα δεδομένα xml

    Λειτουργίες Snap

    Η ιδιότητα Mode ενός αντικειμένου Binding, που αντιπροσωπεύει τη λειτουργία δέσμευσης, μπορεί να λάβει τις ακόλουθες τιμές:

      OneWay: Η ιδιότητα του αντικειμένου προορισμού αλλάζει μετά την τροποποίηση της ιδιότητας του αντικειμένου προέλευσης.

      OneTime: Η ιδιότητα του αντικειμένου προορισμού ορίζεται στην ιδιότητα του αντικειμένου προέλευσης μόνο μία φορά. Μεταγενέστερες αλλαγές στην πηγή δεν έχουν καμία επίδραση στο αντικείμενο προορισμού.

      TwoWay: Τόσο τα αντικείμενα εφαρμογής όσο και τα αντικείμενα πηγής μπορούν να αλλάξουν το ένα τις δεσμευμένες ιδιότητες του άλλου.

      OneWayToSource: Το αντικείμενο προορισμού στο οποίο δηλώνεται η σύνδεση αλλάζει το αντικείμενο προέλευσης.

      Προεπιλογή : από προεπιλογή (αν αλλάξει η ιδιότητα TextBox.Text, έχει την τιμή TwoWay, διαφορετικά OneWay).

    Εφαρμογή της λειτουργίας snap:

    Δεσμευτική ενημέρωση. UpdateSourceTrigger

    Η μονόδρομη σύνδεση από πηγή σε δέκτη αλλάζει την ιδιότητα του δέκτη σχεδόν αμέσως. Αλλά αν χρησιμοποιήσουμε αμφίδρομη σύνδεση στην περίπτωση πεδίων κειμένου (όπως στο παραπάνω παράδειγμα), τότε όταν αλλάζει ο προορισμός, η ιδιότητα προέλευσης δεν αλλάζει αμέσως. Έτσι, στο παραπάνω παράδειγμα, για να αλλάξει το πεδίο κειμένου προέλευσης, πρέπει να μετακινήσουμε την εστίαση από το πεδίο κειμένου προορισμού. Και σε αυτήν την περίπτωση, εμφανίζεται η ιδιότητα UpdateSourceTrigger της κλάσης Binding, η οποία καθορίζει πώς θα γίνει η ενημέρωση. Αυτή η ιδιότητα λαμβάνει μία από τις τιμές απαρίθμησης UpdateSourceTrigger:

      PropertyChanged: Η πηγή σύνδεσης ενημερώνεται αμέσως μετά την ενημέρωση της ιδιότητας στο νεροχύτη

      LostFocus: Η πηγή αγκύρωσης ενημερώνεται μόνο αφού ο δέκτης χάσει την εστίαση

      Ρητό: Η πηγή δεν ενημερώνεται μέχρι να κληθεί η μέθοδος BindingExpression.UpdateSource()

      Προεπιλογή: Προεπιλεγμένη τιμή. Για τις περισσότερες ιδιότητες, αυτό είναι το PropertyChanged . Και για την ιδιότητα Text του στοιχείου TextBox, αυτή η τιμή είναι LostFocus

    Σε αυτήν την περίπτωση, μιλάμε για ενημέρωση της πηγής δέσμευσης μετά την αλλαγή του προορισμού στις λειτουργίες OneWayToSource ή TwoWay. Δηλαδή, ώστε και τα δύο πεδία κειμένου που συνδέονται με τη λειτουργία TwoWay να ενημερώνονται αμέσως μετά την αλλαγή ενός από αυτά, πρέπει να χρησιμοποιήσουμε την τιμή UpdateSourceTrigger.PropertyChanged:

    Ιδιότητα πηγής

    Η ιδιότητα Source σάς επιτρέπει να ορίσετε μια σύνδεση ακόμη και σε αντικείμενα που δεν είναι στοιχεία ελέγχου WPF. Για παράδειγμα, ας ορίσουμε την κλάση Phone:

    Τηλέφωνο τάξης ( δημόσια συμβολοσειρά Τίτλος ( get; set; ) public string Company ( get; set; ) public int Τιμή ( get; set; ) )

    Τώρα ας δημιουργήσουμε ένα αντικείμενο αυτής της κλάσης και ας ορίσουμε μια σύνδεση σε αυτό:

    Ιδιότητα TargetNullValue

    Σε περίπτωση που μια ιδιότητα στην πηγή δέσμευσης έχει ξαφνικά την τιμή null, δηλαδή δεν έχει οριστεί, μπορούμε να ορίσουμε κάποια προεπιλεγμένη τιμή. Για παράδειγμα:

    Σε αυτήν την περίπτωση, ο πόρος nexusPhone δεν έχει σύνολο ιδιοτήτων Title, επομένως το μπλοκ κειμένου θα εξάγει την προεπιλεγμένη τιμή που καθορίζεται στην παράμετρο TargetNullValue.

    Ιδιότητα RelativeSource

    Η ιδιότητα RelativeSource σάς επιτρέπει να ορίσετε μια σύνδεση σε σχέση με ένα στοιχείο προέλευσης που έχει κάποιο είδος σχέσης με το στοιχείο προορισμού. Για παράδειγμα, το στοιχείο προέλευσης μπορεί να είναι ένα από τα εξωτερικά δοχεία για το στοιχείο προορισμού. Ή η πηγή και ο προορισμός μπορεί να είναι το ίδιο στοιχείο.

    Για να ορίσετε αυτήν την ιδιότητα, χρησιμοποιήστε το αντικείμενο RelativeSource με το ίδιο όνομα. Αυτό το αντικείμενο έχει μια ιδιότητα Mode, η οποία καθορίζει τη μέθοδο σύνδεσης. Παίρνει μία από τις τιμές απαρίθμησης RelativeSourceMode:

      Self: η δέσμευση πραγματοποιείται σε μια ιδιότητα του ίδιου στοιχείου. Δηλαδή, το στοιχείο πηγής του δέσιμου είναι ταυτόχρονα και ο δέκτης του δέσιμου.

      FindAncestor: η σύνδεση πραγματοποιείται στην ιδιότητα του στοιχείου κοντέινερ.

    Για παράδειγμα, συνδυάστε τη σύνδεση προέλευσης και προορισμού στο ίδιο το στοιχείο:

    Εδώ το κείμενο και το χρώμα φόντου του πλαισίου κειμένου συνδέονται με αμφίδρομη σύνδεση. Ως αποτέλεσμα, μπορούμε να δούμε στο γήπεδο αριθμητική τιμήχρώμα, αλλάξτε το και το φόντο του πεδίου θα αλλάξει μαζί με αυτό.

    Δέσμευση στις ιδιότητες του δοχείου:

    Όταν χρησιμοποιείτε τη λειτουργία FindAncestor, δηλαδή τη σύνδεση σε ένα κοντέινερ, πρέπει επίσης να καθορίσετε την παράμετρο AncestorType και να της μεταβιβάσετε τον τύπο κοντέινερ με τη μορφή της έκφρασης AncestorType=(x:Type Container_element_type) . Σε αυτήν την περίπτωση, θα μπορούσαμε να επιλέξουμε οποιοδήποτε κοντέινερ στο δέντρο των στοιχείων ως κοντέινερ, σε αυτήν την περίπτωση, εκτός από το Πλέγμα, ένα τέτοιο δοχείο είναι επίσης το στοιχείο Παράθυρο.

    Ιδιότητα DataContext

    Το αντικείμενο FrameworkElement από το οποίο κληρονομούν τα στοιχεία ελέγχου έχει μια ενδιαφέρουσα ιδιότητα DataContext. Σας επιτρέπει να ορίσετε κάποιο πλαίσιο δεδομένων για ένα στοιχείο και τα ένθετα στοιχεία του. Ένθετα στοιχεία μπορούν στη συνέχεια να χρησιμοποιήσουν το αντικείμενο Binding για να συνδεθούν με συγκεκριμένες ιδιότητες αυτού του περιβάλλοντος. Για παράδειγμα, ας χρησιμοποιήσουμε την κλάση Phone που ορίστηκε προηγουμένως και ας δημιουργήσουμε ένα περιβάλλον δεδομένων από ένα αντικείμενο αυτής της κλάσης:

    Με αυτόν τον τρόπο ορίζουμε την ιδιότητα DataContext σε κάποιον δυναμικό ή στατικό πόρο. Στη συνέχεια, δεσμευόμαστε σε αυτόν τον πόρο.

    Σύνδεση δεδομένων σε XAML

    Η κοινή χρήση αντικειμένων σε ένα αρχείο XAML μπορεί επίσης να γίνει μέσω δέσμευσης δεδομένων. Ουσιαστικά δέσμευση δεδομένωνσυνδέει δύο ιδιότητες διαφορετικών αντικειμένων. Όπως θα δείξουμε αργότερα, οι δεσμεύσεις δεδομένων χρησιμοποιούνται συχνότερα για τη συσχέτιση οπτικών σελίδων με πηγές δεδομένων. επιπλέον αποτελούν σημαντικό συστατικό της υλοποίησης του λαϊκού αρχιτεκτονικό μοτίβο MVVM (Model-View-ViewModel). Οι δεσμεύσεις παίζουν επίσης σημαντικό ρόλο στον καθορισμό των μοτίβων εμφάνισης των αντικειμένων δεδομένων.

    Οι δεσμεύσεις δεδομένων μπορούν να χρησιμοποιηθούν για να συσχετίσουν ιδιότητες δύο στοιχείων. Δεσμευτικό στοιχείο, όπως το StaticResource, εκφράζεται συνήθως ως επέκταση σήμανσης, δηλαδή περικλείεται σε σγουρά άγκιστρα. Ωστόσο, το στοιχείο Binding επιτρέπει επίσης μια εναλλακτική έκφραση με τη μορφή σύνταξης στοιχείου ιδιοτήτων.

    Χρησιμοποιήστε το ακόλουθο λεξικό πόρων στο δοκιμαστικό μας έργο:

    Ρυθμίσεις βούρτσας

    Το σιωπηρό στυλ TextBlock δεν περιέχει ιδιότητα Προσκηνίου. Ένα LinearGradientBrush ορίζεται στο πρώτο από τα τέσσερα στοιχεία TextBlock που χρησιμοποιούν αυτό το πινέλο και τα επόμενα στοιχεία TextBlock αναφέρονται στο ίδιο πινέλο μέσω μιας σύνδεσης:

    Η δέσμευση δεδομένων έχει πηγήΚαι δέκτης (στόχος). Ο προορισμός είναι πάντα η ιδιότητα στην οποία έχει οριστεί η δέσμευση και η πηγή είναι η ιδιότητα στην οποία δεσμεύεται. Η πηγή των συνδέσεων που εμφανίζονται είναι ένα στοιχείο TextBlock που ονομάζεται topTxb. Οι δέκτες είναι τρία στοιχεία TextBlock που μοιράζονται την ιδιότητα Foreground. Δύο δέκτες αντιπροσωπεύουν έναν πιο τυπικό τρόπο έκφρασης ενός αντικειμένου Binding ως επέκταση σήμανσης XAML:

    (Binding ElementName=topTxb, Path=Foreground)

    Οι επεκτάσεις σήμανσης XAML τοποθετούνται πάντα μέσα σε σγουρά στηρίγματα. Σε μια επέκταση σήμανσης για Binding, πρέπει συνήθως να ορίσετε ένα ζεύγος ιδιοτήτων, διαχωρισμένων με κόμματα. Ιδιότητα ElementNameυποδηλώνει το όνομα του στοιχείου για το οποίο έχει οριστεί η επιθυμητή ιδιότητα. Ιδιότητα διαδρομήςπαρέχει το όνομα του ακινήτου.

    Όταν πληκτρολογώ επεκτάσεις σήμανσης Binding, θέλω πάντα να περικλείω τιμές ιδιοτήτων σε εισαγωγικά, αλλά αυτό είναι λάθος. Δεν χρειάζονται εισαγωγικά σε δεσμευτικές εκφράσεις.

    Το τελευταίο στοιχείο TextBlock δείχνει την έκφραση Binding σε λιγότερο κοινή σύνταξη στοιχείων ιδιοτήτων:

    Σε αυτήν τη σύνταξη, απαιτούνται εισαγωγικά γύρω από τις τιμές ιδιοτήτων επειδή αυτά είναι συνηθισμένα Χαρακτηριστικά XML. Μπορείτε επίσης να δημιουργήσετε ένα αντικείμενο Binding σε κώδικα και να το αντιστοιχίσετε στην ιδιότητα λήψης χρησιμοποιώντας τη μέθοδο SetBinding()ορίζεται στο FrameworkElement. Αυτό αποκαλύπτει ότι ο δεσμευτικός προορισμός πρέπει πάντα να είναι μια ιδιότητα εξάρτησης.

    Η ιδιότητα Path της κλάσης Binding ονομάζεται έτσι επειδή μπορεί να περιέχει πολλά ονόματα ιδιοτήτων που χωρίζονται με τελείες. Για παράδειγμα, δοκιμάστε να αντικαταστήσετε μία από τις τιμές κειμένου στο έργο σας με την ακόλουθη τιμή:

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

    Το πρώτο μέρος της διαδρομής υποδεικνύει ότι χρειαζόμαστε τα δεδομένα από την ιδιότητα FontFamily. Η ιδιότητα ορίζεται σε ένα αντικείμενο τύπου FontFamily που περιέχει το όνομα Source, το οποίο υποδηλώνει το όνομα της οικογένειας γραμματοσειρών. Επομένως, το TextBlock θα εμφανίσει το κείμενο "Arial".

    Δοκιμάστε να εφαρμόσετε την ακόλουθη κατασκευή σε οποιοδήποτε στοιχείο TextBlock στο έργο μας:

    Text="(Binding RelativeSource=(RelativeSource Self), Path=FontSize)"

    Εδώ είναι η επέκταση σήμανσης RelativeSourceβρίσκεται μέσα στην επέκταση σήμανσης Binding και χρησιμοποιείται για την αναφορά μιας ιδιότητας του στοιχείου για το οποίο έχει οριστεί η σύνδεση.

    Τώρα έχετε δημιουργήσει πλήρεις σελίδες για την εφαρμογή σας. Τώρα μάλλον θα θέλετε να τα γεμίσετε με διάφορα δεδομένα.

    Σε αυτό το μέρος θα μάθετε:

    • Πώς να συνδέσετε δεδομένα στη διεπαφή χρήστη.
    • Πως Visual Studioμπορεί να σας βοηθήσει να δημιουργήσετε δεσμεύσεις δεδομένων.
    • Πώς να εμφανίσετε δεδομένα σε μια λίστα.
    • Πώς να αντιμετωπίσετε πιο σύνθετα δεσμευτικά σενάρια.

    Σύνδεση δεδομένων στη διεπαφή χρήστη

    Η εφαρμογή Fuel Tracker έχει τρεις σελίδες δεδομένων. Τα δεδομένα αποθηκεύονται κυρίως σε τρεις κατηγορίες. Η παρακάτω εικόνα δείχνει τις σελίδες και τις σχετικές κλάσεις τους.

    Η σύνδεση δεδομένων χρησιμοποιείται συνήθως για την εμφάνιση δεδομένων. Η σύνδεση δεδομένων παρέχει τη δυνατότητα σύνδεσης μιας διεπαφής χρήστη σε μια πηγή δεδομένων. Όταν δημιουργούνται δεσμεύσεις και αλλάζει η πηγή δεδομένων, τα στοιχεία διεπαφής χρήστη που συνδέονται με την πηγή δεδομένων αντικατοπτρίζουν αυτόματα τις αλλαγές. Ομοίως, οι αλλαγές που γίνονται από τον χρήστη σε ένα στοιχείο διεπαφής χρήστη αντικατοπτρίζονται στην πηγή δεδομένων. Για παράδειγμα, εάν ο χρήστης αλλάξει μια τιμή σε ένα TextBox, η αντίστοιχη πηγή δεδομένων θα ενημερωθεί αυτόματα για να αντικατοπτρίζει αυτές τις αλλαγές.

    Το ακόλουθο απόσπασμα κώδικα XAML απεικονίζει τη σύνταξη που χρησιμοποιείται για τη σύνδεση της ιδιότητας Text ενός στοιχείου ελέγχου TextBox με την ιδιότητα Name του αντικειμένου προέλευσης.

    1. < TextBox x:Name ="NameTextBox" Text ="(Binding Name, Mode=TwoWay)" />

    Η παρακάτω εικόνα δείχνει ένα παράδειγμα τέτοιου δέσιμου.

    Κάθε δέσμευση έχει μια ιδιότητα Mode, η οποία καθορίζει πώς και πότε ενημερώνονται τα δεδομένα. Η δέσμευση OneWay σημαίνει ότι το στοιχείο διεπαφής χρήστη προορισμού ενημερώνεται εάν αλλάξει η πηγή. Η αμφίδρομη δέσμευση σημαίνει ότι τόσο ο στόχος όσο και η πηγή ενημερώνονται εάν αλλάξει κάποιο από αυτά. Εάν χρησιμοποιείτε συνδέσεις OneWay ή TwoWay, τότε για να ειδοποιηθεί η σύνδεση για αλλαγές στο αντικείμενο προέλευσης, πρέπει να εφαρμόσετε τη διεπαφή INotifyPropertyChanged. Αυτή η διεπαφή θα συζητηθεί με περισσότερες λεπτομέρειες στο επόμενο μέρος, «Δημιουργία κλάσεων δεδομένων».

    Καθορίζετε ένα αντικείμενο προέλευσης ορίζοντας την ιδιότητα DataContext. Εάν χρησιμοποιείτε ένα στοιχείο ελέγχου ListBox, πρέπει να καθορίσετε το αντικείμενο προέλευσης ορίζοντας την ιδιότητα ItemsSource. Το ακόλουθο παράδειγμα δείχνει πώς να ορίσετε την ιδιότητα DataContext του πίνακα CarHeader σε ένα αντικείμενο προέλευσης που ανακτάται από μια στατική ιδιότητα.

    1. CarHeader.DataContext = CarDataStore.Car;
    * Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

    Η ιδιότητα DataContext σάς επιτρέπει να ορίσετε μια τυπική δέσμευση για ένα ολόκληρο στοιχείο διεπαφής χρήστη, συμπεριλαμβανομένων όλων των θυγατρικών του στοιχείων. Σε ορισμένες περιπτώσεις, θα είναι πιο βολικό να ορίσετε την ιδιότητα DataContext για ολόκληρη τη σελίδα και σε άλλες, θα σας φανεί πιο βολικό να τη ρυθμίσετε μεμονωμένα για κάθε στοιχείο της σελίδας. Η ρύθμιση του DataContext σε κάθε επίπεδο XAML παρακάμπτει τυχόν ρυθμίσεις σε υψηλότερο επίπεδο. Επιπλέον, μπορείτε πραγματικά να παρακάμψετε οποιαδήποτε ρύθμιση DataContext για μεμονωμένες δεσμεύσεις ορίζοντας την ιδιότητα Source.

    Για παράδειγμα, στην εφαρμογή Fuel Tracker, κάθε σελίδα ορίζει το DataContext σε διαφορετική τιμή. Ωστόσο, στη σελίδα FillupPageΤο DataContext σε επίπεδο σελίδας παρακάμπτεται για τον πίνακα που εμφανίζει το όνομα και τη φωτογραφία του αυτοκινήτου. Η παρακάτω εικόνα δείχνει τις ρυθμίσεις περιβάλλοντος δεδομένων για την εφαρμογή Fuel Tracker.

    Χρήση του εργαλείου δημιουργίας σύνδεσης δεδομένων

    Το Visual Studio περιλαμβάνει ένα εργαλείο δημιουργίας σύνδεσης δεδομένων για να σας βοηθήσει να δημιουργήσετε δεσμεύσεις δεδομένων στο XAML. Αν και το εργαλείο δημιουργίας σύνδεσης δεδομένων μπορεί να προσφέρει βελτιώσεις απόδοσης, δεν υποστηρίζει κάθε πιθανό σενάριο. Για παράδειγμα, δεν υποστηρίζει σύνδεση σε στοιχεία με ευρετήριο και δεν αναγνωρίζει δεσμεύσεις που δημιουργούνται σε κώδικα. Επομένως, σε ορισμένες περιπτώσεις θα χρειαστεί να καθορίσετε τις δεσμεύσεις δεδομένων με μη αυτόματο τρόπο.

    Εμφάνιση δεδομένων σε λίστα

    Η εμφάνιση μιας συλλογής στοιχείων σε μια λίστα είναι μία από τις κύριες εργασίες στο τηλέφωνό σας. Για να εμφανίσετε μια συλλογή στοιχείων σε μια λίστα χρησιμοποιώντας δέσμευση δεδομένων, πρέπει να κάνετε τα εξής:
    1. Προσθέστε ListBox στην εφαρμογή σας.
    2. Καθορίστε την προέλευση δεδομένων για το ListBox δεσμεύοντας τη συλλογή στην ιδιότητα ItemsSource.
    3. Για να προσαρμόσετε την εμφάνιση κάθε στοιχείου σε ένα ListBox, προσθέστε ένα πρότυπο δεδομένων για το ListBox.
    4. Στο πρότυπο δεδομένων, συνδέστε τα στοιχεία ListBox με τις ιδιότητες συλλογής στοιχείων.
    Η παρακάτω εικόνα δείχνει τις συνδέσεις για το ListBox στη σελίδα σύνοψης της εφαρμογής παρακολούθησης καυσίμου.

    Το ακόλουθο XAML δείχνει πώς καθορίστηκαν οι δεσμεύσεις για το ListBox.

    1. < ListBox ItemContainerStyle ="(StaticResource ListBoxStyle)"
    2. ItemsSource="(Binding FillupHistory)"
    3. Height="380" HorizontalAlignment="Αριστερό" Περιθώριο="5.25,0.0"
    4. VerticalAlignment="Top" Width="444" >
    5. < ListBox.ItemTemplate >
    6. < DataTemplate >
    7. < StackPanel Orientation ="Horizontal" >
    8. < TextBlock Style
    9. Κείμενο ="(Binding Date, Converter=(StaticResource StringFormatter), ConverterParameter=\(0:d\) )"
    10. Width="105" TextWrapping="Wrap" />
    11. < TextBlock Style ="(StaticResource SummaryStyle)"
    12. Κείμενο ="(Binding FuelQuantity)" TextWrapping ="Wrap" />
    13. < TextBlock Style ="(StaticResource SummaryStyle)"
    14. Κείμενο ="(Binding DistanceDriven)" TextWrapping ="Wrap" />
    15. < TextBlock Style ="(StaticResource SummaryStyle)"
    16. Text ="(Binding PricePerFuelUnit, Converter=(StaticResource StringFormatter), ConverterParameter=\(0:c\), ConverterCulture=en-US)" />
    17. < TextBlock Style ="(StaticResource SummaryStyle)"
    18. Κείμενο ="(Binding FuelEfficiency, Converter=(StaticResource StringFormatter), ConverterParameter=\(0:F\))" TextWrapping ="Wrap" />
    * Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

    Στο προηγούμενο XAML, η ιδιότητα ListBox.ItemsSource είναι δεσμευμένη στο Car.FillupHistoryώστε κάθε αντικείμενο Fillupστη συλλογή ιστορικού θα εμφανιστεί ως ξεχωριστό στοιχείο στο ListBox. Το στοιχείο DataTemplate ορίζει την εμφάνιση κάθε στοιχείου και περιέχει πολλά στοιχεία TextBlock, καθένα από τα οποία είναι δεσμευμένο σε μια ιδιότητα κλάσης Fillup.

    Αυτό το XAML θα λειτουργήσει μόνο όταν το αντικείμενο Αυτοκίνητοσυσχετίζεται πρώτα με τη σελίδα, όπως φαίνεται στον παρακάτω κώδικα από το SummaryPage.xaml.cs.

    1. αυτό το .DataContext = CarDataStore.Car;
    * Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

    Συμβουλή για τη βελτίωση της απόδοσης:
    Εάν η κύλιση στο ListBox σας δεν φαίνεται ομαλή και αποκρίνεται, δοκιμάστε αυτές τις συμβουλές:
    • Απλοποιήστε τα στοιχεία στο ListBox.
    • Φόρτωση εικόνων στο παρασκήνιο.
    • Χρησιμοποιήστε εικονικοποίηση δεδομένων.
    • Σημειώστε τη χρήση του DeferredLoadListBox ή του LazyListBox.
    • Μην χρησιμοποιείτε ένθετες λίστες.

    Σύνθετες διαδρομές σύνδεσης

    Εκτός από την ευελιξία της ρύθμισης της ιδιότητας DataContext σε οποιοδήποτε επίπεδο (που σας επιτρέπει να παρακάμψετε ρυθμίσεις σε υψηλότερο επίπεδο), μπορείτε επίσης να καθορίσετε σύνθετες διαδρομές δέσμευσης για να διερευνήσετε τις ιδιότητες αναφοράς, όπως π.χ. Car.FillupHistory. Για παράδειγμα, το ακόλουθο XAML από το SummaryPage.xaml δείχνει τη σύνδεση ιδιοτήτων Fillup.FuelEfficiencyτο πρώτο στοιχείο στη συλλογή της ιστορίας του βενζινάδικου.
    1. < TextBlock Text ="(Binding FillupHistory.FuelEfficiency, Converter=(StaticResource StringFormatter), ConverterParameter=\(0:F\))" />
    * Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

    Η παρακάτω εικόνα δείχνει τις συνδέσεις στο SummaryPage.xaml και δείχνει πώς σύνθετες δεσμεύσειςκαι τα πρότυπα δεδομένων σάς επιτρέπουν να συνδέετε στοιχεία ελέγχου σε διαφορετικές ιδιότητες διαφορετικών αντικειμένων, ακόμα κι αν ανήκουν όλα στο ίδιο DataContext.

    Τα πράσινα ορθογώνια στην αριστερή οθόνη Περιστροφής εμφανίζουν στοιχεία ελέγχου που είναι συνδεδεμένα χρησιμοποιώντας δύσκολα μονοπάτια. Αυτές οι διαδρομές ξεκινούν από το πρώτο στοιχείο (ευρετήριο 0) στη συλλογή Car.FillupHistoryκαι τελειώνουν με διάφορες ιδιότητες κλάσης Fillup. Για παράδειγμα, το πεδίο Current MPG χρησιμοποιεί τη διαδρομή δέσμευσης FillupHistory.FuelEfficiency. Εάν συμπεριλάβετε τη ρύθμιση DataContext της σελίδας σε αυτήν τη διαδρομή, ολόκληρη η διαδρομή δέσμευσης θα μοιάζει με αυτό: CarDataStore.Car.FillupHistory.FuelEfficiency.

    Ετικέτες:

    • windows phone 7
    • δημιουργία μιας εφαρμογής
    • από την αρχή μέχρι το τέλος
    Προσθήκη ετικετών

    Όταν το Windows Presentation Foundation (WPF) εμφανίστηκε για πρώτη φορά στο ραντάρ .NET, τα περισσότερα άρθρα και επιδείξεις διαφημίζονταν για την κορυφαία μηχανή απόδοσης και τις δυνατότητες τρισδιάστατων γραφικών του. Αν και είναι διασκεδαστικό να διαβάζεις και να παίζεις, αυτά τα παραδείγματα δεν αντικατοπτρίζουν τις ευρείες δυνατότητες του WPF στον πραγματικό κόσμο. Οι περισσότεροι από εμάς δεν χρειάζεται να δημιουργήσουμε εφαρμογές με περιστρεφόμενους κύβους βίντεο που εκρήγνυνται σε πυροτεχνήματα όταν πατηθούν. Οι περισσότεροι από εμάς βγάζουμε τα προς το ζην δημιουργώντας λογισμικόγια την εμφάνιση και την επεξεργασία μεγάλων όγκων πολύπλοκων επιστημονικών ή επιχειρηματικών δεδομένων.

    Τα καλά νέα είναι ότι το WPF προσφέρει εξαιρετική υποστήριξη για τη διαχείριση της εμφάνισης και της επεξεργασίας πολύπλοκων δεδομένων. Στο τεύχος Δεκεμβρίου 2007 του περιοδικού MSDN®, ο John Papa έγραψε ένα άρθρο, «Δέσμευση δεδομένων στο WPF» (msdn.microsoft.com/magazine/cc163299), το οποίο κάνει εξαιρετική δουλειά εξηγώντας τις βασικές έννοιες της δέσμευσης δεδομένων στο WPF. Εδώ θα εξετάσω πιο περίπλοκες περιπτώσεις δέσμευσης δεδομένων, βασιζόμενοι σε όσα παρουσίασε ο John στην προαναφερθείσα σειρά Data Points. Αφού διαβάσουν αυτό, οι αναγνώστες θα γνωρίζουν διάφορους τρόπους εφαρμογής κοινών απαιτήσεων δέσμευσης δεδομένων που εμφανίζονται στις περισσότερες επιχειρηματικές εφαρμογές.

    Δέσμευση σε κώδικα

    Μία από τις μεγαλύτερες αλλαγές που εισάγει το WPF στους προγραμματιστές επιτραπέζιων εφαρμογών είναι η ευρεία χρήση και η υποστήριξη του δηλωτικού προγραμματισμού. Οι διεπαφές χρήστη και οι πόροι του WPF μπορούν να δηλωθούν χρησιμοποιώντας τη γλώσσα σήμανσης επεκτάσιμης εφαρμογής (XAML), μια τυπική γλώσσα σήμανσης που βασίζεται σε XML. Οι περισσότερες εξηγήσεις του δεσμευτικού Δεδομένα WPFΣας δείχνουν μόνο πώς να εργάζεστε με δεσμεύσεις στο XAML. Δεδομένου ότι ό,τι μπορεί να γίνει στο XAML μπορεί να επιτευχθεί και σε κώδικα, είναι σημαντικό αυτό επαγγελματίες προγραμματιστέςστο πλαίσιο του WPF ήξεραν πώς να εργάζονται με τη δέσμευση δεδομένων όχι μόνο δηλωτικά, αλλά και προγραμματικά.

    Σε πολλές περιπτώσεις, είναι ευκολότερο και πιο βολικό να δηλώσετε δεσμεύσεις στο XAML. Καθώς τα συστήματα γίνονται πιο πολύπλοκα και δυναμικά, μερικές φορές είναι λογικό να δουλεύουμε με δεσμεύσεις στον κώδικα. Πριν προχωρήσουμε περαιτέρω, ας δούμε πρώτα μερικές κοινές κλάσεις και μεθόδους που εμπλέκονται στη σύνδεση δεδομένων μέσω προγραμματισμού.

    Τα στοιχεία WPF κληρονομούν τις μεθόδους SetBinding και GetBindingExpression είτε από το FrameworkElement είτε από το FrameworkContentElement. Αυτές είναι απλώς μέθοδοι ευκολίας που καλούν μεθόδους με τα ίδια ονόματα στην κλάση βοηθητικού προγράμματος BindingOperations. Ο ακόλουθος κώδικας δείχνει πώς να χρησιμοποιήσετε την κλάση BindingOperations για να συνδέσετε την ιδιότητα Text ενός πλαισίου κειμένου σε μια ιδιότητα σε άλλο αντικείμενο:

    Static void BindText (TextBox textBox, ιδιότητα συμβολοσειράς)
    {
    if (!BindingOperations.IsDataBound(TextBox, textProp))
    {
    Binding b = new Binding(ιδιότητα);
    BindingOperations.SetBinding(TextBox, textProp, b);
    }
    }

    Είναι εύκολο να αποδεσμεύσετε μια ιδιότητα χρησιμοποιώντας τον ακόλουθο κώδικα:

    Static void UnbindText (TextBox textBox)
    {
    DependencyProperty textProp = TextBox.TextProperty;
    if (BindingOperations.IsDataBound(TextBox, textProp))
    {
    BindingOperations.ClearBinding(textBox, textProp);
    }
    }

    Κατά την εκκαθάριση μιας δέσμευσης, η δεσμευμένη τιμή αφαιρείται επίσης από την ιδιότητα προορισμού.

    Η δήλωση δεσμευτικών δεδομένων στο XAML κρύβει ορισμένες από τις υποκείμενες λεπτομέρειες. Όταν ξεκινάτε να εργάζεστε με δεσμεύσεις σε κώδικα, αυτές οι λεπτομέρειες αρχίζουν να εμφανίζονται. Το ένα είναι ότι η σχέση μεταξύ της πηγής μιας σύνδεσης και του στόχου της διατηρείται στην πραγματικότητα από μια παρουσία της κλάσης BindingExpression και όχι από την ίδια την κλάση Binding. Η κλάση Binding περιέχει πληροφορίες υψηλού επιπέδου που μπορούν να κοινοποιηθούν από πολλές κλάσεις BindingExpression, αλλά η υποκείμενη έκφραση παρέχει τη σύνδεση μεταξύ δύο δεσμευμένων ιδιοτήτων. Ο ακόλουθος κώδικας δείχνει πώς μπορεί να χρησιμοποιηθεί μια BindingExpression για να διασφαλιστεί μέσω προγραμματισμού ότι είναι επιλεγμένη η ιδιότητα Text ενός πλαισίου κειμένου:

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

    var expr = textBox.GetBindingExpression(textProp);
    εάν (expr == null)
    επιστροφή ψευδής?

    Binding b = expr.ParentBinding;
    επιστροφή b.ValidationRules.Any();
    }

    Εφόσον η κλάση BindingExpression δεν γνωρίζει ότι επικυρώνεται, πρέπει να τεθεί το ερώτημα σχετικά με τη γονική της δέσμευση. Θα συζητήσω διάφορες τεχνικές επικύρωσης εισόδου παρακάτω.

    Εργασία με Πρότυπα

    Μια αποτελεσματική διεπαφή χρήστη παρουσιάζει ακατέργαστα δεδομένα με τρόπο που επιτρέπει στον χρήστη να εξάγει διαισθητικά σημαντικές πληροφορίες από αυτά. Αυτή είναι η ουσία της οπτικοποίησης δεδομένων. Η σύνδεση δεδομένων είναι μόνο ένα κομμάτι του παζλ οπτικοποίησης δεδομένων. Όλα εκτός από τα πιο ασήμαντα προγράμματα WPF απαιτούν έναν τρόπο αναπαράστασης δεδομένων που είναι πιο ισχυρός από την απλή σύνδεση μιας ιδιότητας στο στοιχείο ελέγχου σε μια ιδιότητα στο αντικείμενο δεδομένων. Τα πραγματικά αντικείμενα δεδομένων έχουν πολλές ιδιότητες που σχετίζονται με αυτά και αυτές οι διαφορετικές ιδιότητες πρέπει να συγκλίνουν σε μια συνεκτική οπτική αναπαράσταση. Αυτός είναι ο λόγος για τον οποίο το WPF έχει πρότυπα δεδομένων.

    Η κλάση System.Windows.DataTemplate είναι μόνο μια μορφή προτύπου στο WPF. Βασικά, ένα πρότυπο είναι ένας κόφτης cookie που χρησιμοποιεί το πλαίσιο WPF για τη δημιουργία οπτικών στοιχείων που βοηθούν στην απόδοση αντικειμένων που δεν έχουν τη δική τους οπτική αναπαράσταση. Όταν ένα στοιχείο επιχειρεί να αποδώσει ένα αντικείμενο που δεν έχει τέτοια αναπαράσταση, ας πούμε ένα μη τυπικό επιχειρηματικό αντικείμενο, μπορείτε να πείτε στο στοιχείο πώς να αποδώσει το αντικείμενο δίνοντάς του ένα DataTemplate.
    Ένα DataTemplate μπορεί να δημιουργήσει όσες εικόνες χρειάζονται για την εμφάνιση ενός αντικειμένου δεδομένων. Αυτά τα στοιχεία χρησιμοποιούν δεσμεύσεις δεδομένων για να εμφανίσουν την τιμή των ιδιοτήτων ενός αντικειμένου δεδομένων. Εάν ένα στοιχείο δεν ξέρει πώς να αποδώσει το αντικείμενο που του ζητήθηκε να αποδώσει, καλεί απλώς τη μέθοδο ToString σε αυτό και εμφανίζει τα αποτελέσματα σε ένα TextBlock.

    Ας υποθέσουμε ότι έχουμε μια απλή κλάση που ονομάζεται FullName που αποθηκεύει το όνομα ενός ατόμου. Θέλετε να εμφανίσετε μια λίστα ονομάτων που κάνει το επώνυμο κάθε ατόμου να ξεχωρίζει από τα υπόλοιπα. Για να το κάνετε αυτό, μπορείτε να δημιουργήσετε ένα DataTemplate που περιγράφει τον τρόπο απόδοσης του αντικειμένου FullName. Ο κώδικας που φαίνεται στο Σχ. 1, εμφανίζει την κλάση FullName και τον κωδικό φόντου για ένα παράθυρο που θα εμφανίζει μια λίστα ονομάτων.

    Ρύζι. 1. Εμφάνιση αντικειμένων FullName χρησιμοποιώντας DataTemplate

    δημόσια τάξη Πλήρες Όνομα
    {
    δημόσια συμβολοσειρά FirstName ( get; set; )
    δημόσιος χαρακτήρας MiddleInitial ( get; set; )
    δημόσια συμβολοσειρά Επώνυμο ( get; set; )
    }

    δημόσια μερική τάξη WorkingWithTemplates: Παράθυρο
    {
    // Αυτός είναι ο κατασκευαστής του παραθύρου.
    δημόσιο WorkingWithTemplates()
    {
    InitializeComponent();

    base.DataContext = νέο FullName
    {
    νέο Ονοματεπώνυμο
    {
    FirstName = "Johann",
    MiddleInitial = "S",
    Επώνυμο = "Μπαχ"
    },
    νέο Ονοματεπώνυμο
    {
    FirstName = "Gustav",
    MiddleInitial = " ",
    Επώνυμο = "Mahler"
    },
    νέο Ονοματεπώνυμο
    {
    FirstName = "Alfred",
    MiddleInitial = "G",
    Επώνυμο = "Schnittke"
    }
    };
    }
    }

    Όπως φαίνεται στο Σχ. 2, Υπάρχει ένα στοιχείο ελέγχου ItemsControl στο αρχείο XAML του παραθύρου. Δημιουργεί μια απλή λίστα στοιχείων που ο χρήστης δεν μπορεί να επιλέξει ή να διαγράψει. Το ItemsControl έχει ένα πρότυπο DataTemplate που έχει εκχωρηθεί στην ιδιότητά του ItemTemplate, με το οποίο αποδίδει κάθε στιγμιότυπο FullName που δημιουργείται στον κατασκευαστή του παραθύρου. Θα παρατηρήσετε ότι τα περισσότερα στοιχεία TextBlock στο DataTemplate έχουν την ιδιότητα Text τους συνδεδεμένη με τις ιδιότητες του αντικειμένου FullName που αντιπροσωπεύουν.

    Ρύζι. 2. Εμφάνιση αντικειμένων FullName χρησιμοποιώντας DataTemplate














    Όταν εκτελείτε αυτήν την εφαρμογή επίδειξης, μοιάζει με το Σχ. 3. Η χρήση ενός DataTemplate για την απόδοση ενός ονόματος διευκολύνει την επισήμανση του επωνύμου κάθε ατόμου, επειδή η ρύθμιση FontWeight του αντίστοιχου TextBlock είναι έντονη. Αυτό το απλό παράδειγμα δείχνει τη σχέση μεταξύ της σύνδεσης δεδομένων WPF και των προτύπων. Καθώς εμβαθύνω στο θέμα, θα συνδυάσω αυτά τα χαρακτηριστικά για να δημιουργήσω τρόπους οπτικοποίησης σύνθετων αντικειμένων με συνεχώς αυξανόμενες δυνατότητες.

    Ρύζι. 3. Αντικείμενα FullName που αποδίδονται από το DataTemplate

    Εργασία με Κληρονομικό DataContext

    Εκτός εάν ορίζεται διαφορετικά, όλες οι δεσμεύσεις συνδέονται έμμεσα με την ιδιότητα DataContext του στοιχείου. Το DataContext ενός στοιχείου αναφέρεται στην πηγή δεδομένων του, ας πούμε έτσι. Υπάρχουν μερικά ειδικά πράγματα που πρέπει να γνωρίζετε σχετικά με τον τρόπο λειτουργίας του DataContext. Η κατανόηση αυτής της σιωπηρής πτυχής του DataContext καθιστά πολύ πιο εύκολο τον σχεδιασμό σύνθετων διεπαφών χρήστη που συνδέονται με δεδομένα.

    Για να αναφερθείτε σε ένα αντικείμενο προέλευσης δεδομένων, δεν είναι απαραίτητο να ορίσετε την ιδιότητα DataContext. Εάν η ιδιότητα DataContext ενός προγονικού στοιχείου σε ένα δέντρο στοιχείων (τεχνικά μιλώντας, ένα λογικό δέντρο) λάβει μια τιμή για το DataContext του, τότε η τιμή θα κληρονομηθεί αυτόματα από κάθε παράγωγο στοιχείο στη διεπαφή χρήστη. Με άλλα λόγια, εάν το DataContext έχει οριστεί να αναφέρεται σε ένα αντικείμενο Foo, τότε, από προεπιλογή, το DataContext κάθε στοιχείου στο παράθυρο θα αναφέρεται στο ίδιο αντικείμενο Foo. Σε οποιοδήποτε στοιχείο σε ένα παράθυρο μπορεί εύκολα να δοθεί η δική του τιμή DataContext, η οποία θα κάνει όλα τα στοιχεία που προέρχονται από αυτό το στοιχείο να κληρονομήσουν τη νέα τιμή DataContext. Αυτό είναι παρόμοιο με μια εξωτερική ιδιότητα στις Φόρμες των Windows.

    Στην προηγούμενη ενότητα, εξέτασα τη χρήση των DataTemplates για τη δημιουργία οπτικοποιήσεων αντικειμένων δεδομένων. Ιδιότητες στοιχείων που δημιουργούνται από το πρότυπο στο Σχ. 2 συνδέονται με τις ιδιότητες του αντικειμένου FullName. Αυτά τα στοιχεία συνδέονται έμμεσα με την ιδιότητά τους DataContext. Η ιδιότητα DataContext των στοιχείων που δημιουργούνται από το πρότυπο DataTemplate αναφέρεται στο αντικείμενο δεδομένων για το οποίο χρησιμοποιείται το πρότυπο, όπως ένα αντικείμενο FullName.

    Δεν υπάρχει καμία μαγεία στην κληρονομιά της τιμής της ιδιότητας DataContext. Αυτό χρησιμοποιεί απλώς την ενσωματωμένη υποστήριξη του WPF για ιδιότητες κληρονομικής εξάρτησης. Οποιαδήποτε ιδιότητα εξάρτησης μπορεί να είναι κληρονομική ιδιότητα εάν απλώς της δοθεί μια σημαία στα μεταδεδομένα που παρέχονται κατά την εγγραφή αυτής της ιδιότητας στο σύστημα ιδιοτήτων εξαρτήσεων WPF.

    Ένα άλλο παράδειγμα μιας κληρονομούμενης ιδιότητας εξάρτησης είναι η ιδιότητα Font-Size που έχουν όλα τα στοιχεία. Εάν ορίσετε την ιδιότητα εξάρτησης FontSize σε ένα παράθυρο, τότε από προεπιλογή όλα τα στοιχεία σε αυτό το παράθυρο θα εμφανίζονται ως κείμενο στο μέγεθος γραμματοσειράς που καθορίζεται από αυτό. Η υποδομή που χρησιμοποιείται για τη διάδοση της τιμής FontSize προς τα κάτω στο δέντρο στοιχείων διαδίδει επίσης το DataContext.

    Εδώ ο όρος "κληρονομικότητα" χρησιμοποιείται με μια έννοια διαφορετική από την αντικειμενοστραφή έννοιά του, όπου μια υποκλάση κληρονομεί μέλη της γονικής κλάσης. Η κληρονομικότητα των τιμών των ιδιοτήτων αναφέρεται μόνο στη διάδοση των τιμών στο δέντρο στοιχείων κατά το χρόνο εκτέλεσης. Φυσικά, μια κλάση μπορεί να κληρονομήσει μια ιδιότητα εξάρτησης για να υποστηρίξει την κληρονομικότητα αξίας με αντικειμενοστραφή έννοια.

    Εργασία με Προβολές Συλλογών

    Όταν τα στοιχεία ελέγχου WPF συνδέονται με μια συλλογή δεδομένων, δεν συνδέονται απευθείας με την ίδια τη συλλογή. Αντίθετα, συνδέονται έμμεσα με μια προβολή, η οποία γίνεται αυτόματα το περιτύλιγμα αυτής της συλλογής. Η προβολή υλοποιεί τη διεπαφή ICollectionViews και μπορεί να είναι μία από πολλές συγκεκριμένες υλοποιήσεις, όπως το ListCollectionView.

    Η παρουσίαση μιας συλλογής έχει πολλές εργασίες. Παρακολουθεί το τρέχον στοιχείο στη συλλογή, το οποίο είναι συνήθως το επιλεγμένο/ενεργό στοιχείο σε ένα στοιχείο ελέγχου πλαισίου λίστας. Οι προβολές συλλογής προσφέρουν επίσης γενικούς τρόπους παραγγελίας, φιλτραρίσματος και ομαδοποίησης στοιχείων σε μια λίστα. Πολλά χειριστήρια μπορούν να συνδεθούν στην ίδια προβολή γύρω από μια συλλογή, διασφαλίζοντας τον συντονισμό τους μεταξύ τους. Ο παρακάτω κώδικας δείχνει μερικές από τις δυνατότητες του ICollectionView:

    // Λάβετε την προεπιλεγμένη προβολή τυλιγμένη στη λίστα των πελατών.
    Προβολή ICollectionView = CollectionViewSource.GetDefaultView(allCustomers);

    // Επιλογή του πελάτη στη διεπαφή χρήστη.
    Επιλεγμένος πελάτηςΠελάτης = προβολή.ΤρέχονΣτοιχείο ως Πελάτης.

    // Ορίστε τον επιλεγμένο πελάτη στη διεπαφή χρήστη.
    προβολή.MoveCurrentTo(someOtherCustomer);

    Όλα τα στοιχεία ελέγχου τύπου λίστας, συμπεριλαμβανομένων των πλαισίων λίστας, των σύνθετων πλαισίων και των προβολών λίστας, πρέπει να έχουν την ιδιότητα IsSynchronizedWithCurrentItem οριστεί σε true για να παραμείνουν συγχρονισμένα με την ιδιότητα προβολής συλλογής CurrentItem. Αυτή η ιδιότητα ορίζει αφηρημένη τάξηΕκλέκτορας. Εάν δεν έχει οριστεί σε true, τότε η επιλογή ενός στοιχείου στο στοιχείο ελέγχου πλαισίου λίστας δεν θα ενημερώσει το CurrentItem της προβολής συλλογής και η ρύθμιση του CurrentItem σε μια νέα τιμή δεν θα αντικατοπτρίζεται στο στοιχείο ελέγχου πλαισίου λίστας.

    Εργασία με Ιεραρχικά Δεδομένα

    Ο πραγματικός κόσμος είναι γεμάτος ιεραρχικά δεδομένα. Ένας πελάτης δίνει πολλές παραγγελίες, ένα μόριο αποτελείται από πολλά άτομα, ένα τμήμα αποτελείται από πολλούς υπαλλήλους και ηλιακό σύστημαπεριέχει μια ομάδα ουράνιων σωμάτων. Οι αναγνώστες είναι αναμφίβολα εξοικειωμένοι με αυτό το κύριο/λεπτομέρεια σχήμα.
    Το WPF παρέχει διαφορετικούς τρόπους εργασίας με ιεραρχικές δομές δεδομένων, ο καθένας κατάλληλος για διαφορετικές καταστάσεις. Ουσιαστικά, η εναλλακτική είναι είτε η χρήση πολλαπλών στοιχείων ελέγχου για την εμφάνιση δεδομένων, είτε η εμφάνιση πολλαπλών επιπέδων ιεραρχίας δεδομένων σε ένα μόνο στοιχείο ελέγχου. Εδώ θα αναλύσω και τις δύο αυτές προσεγγίσεις.

    Χρήση πολλαπλών στοιχείων ελέγχου για την εμφάνιση δεδομένων XML

    Ένας πολύ συνηθισμένος τρόπος εργασίας με ιεραρχικά δεδομένα είναι η εμφάνιση κάθε επιπέδου της ιεραρχίας ως ξεχωριστό στοιχείο ελέγχου. Για παράδειγμα, ας υποθέσουμε ότι έχουμε ένα σύστημα που αντιπροσωπεύει πελάτες, παραγγελίες και λεπτομέρειες παραγγελιών. Σε μια τέτοια περίπτωση, ένα σύνθετο πλαίσιο μπορεί να χρησιμοποιηθεί για την εμφάνιση των πελατών, ένα πλαίσιο λίστας για την εμφάνιση όλων των παραγγελιών των επιλεγμένων πελατών και, τέλος, ένα ItemsControl για την εμφάνιση των λεπτομερειών της επιλεγμένης παραγγελίας. Αυτό υπέροχος τρόποςΗ εμφάνιση ιεραρχικών δεδομένων και η εφαρμογή τους στο WPF είναι αρκετά εύκολη.

    Στο Σχ. Το σχήμα 4, με βάση την κατάσταση που περιγράφεται παραπάνω, δείχνει ένα απλοποιημένο παράδειγμα των δεδομένων με τα οποία μπορεί να λειτουργήσει μια εφαρμογή, τυλιγμένα σε ένα στοιχείο WPF XmlDataProvider. Αυτά τα δεδομένα μπορούν να εμφανιστούν σε μια διεπαφή χρήστη παρόμοια με αυτή που φαίνεται στην Εικ. 5. Λάβετε υπόψη ότι οι πελάτες και οι παραγγελίες μπορούν να επιλεγούν, αλλά τα στοιχεία της παραγγελίας υπάρχουν σε μορφή λίστας μόνο για ανάγνωση. Υπάρχει ένας λόγος για αυτό - η δυνατότητα επιλογής ενός οπτικού αντικειμένου θα πρέπει να παρέχεται μόνο όταν επηρεάζει την κατάσταση της εφαρμογής ή είναι μεταβλητό.

    Ρύζι. 4. Ιεραρχία παραγγελιών πελατών και πληροφορίες παραγγελιών σε μορφή XML





















    Ρύζι. 5 Ένας τρόπος εμφάνισης δεδομένων XML

    Στον κώδικα XAML στο Σχ. Το Σχήμα 6 περιγράφει τον τρόπο χρήσης αυτών των διαφόρων στοιχείων ελέγχου για την εμφάνιση των ιεραρχικών δεδομένων που μόλις παρουσιάστηκαν. Αυτό το παράθυρο δεν απαιτεί κωδικό. υπάρχει εξ ολοκλήρου στον κώδικα XAML.

    Ρύζι. 6. Κώδικας XAML για τη σύνδεση ιεραρχικών δεδομένων XML στη διεπαφή χρήστη

    "(Binding Source=(StaticResource xmlData),
    XPath=πελάτες/πελάτες)"
    Περιθώριο = "4"
    >







    ItemsSource="(Binding)"
    >









    x:Name="orderSelector"
    DataContext="(Binding Path=CurrentItem)"
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="(Binding XPath=order)"
    >








    Text="Λεπτομέρειες παραγγελίας" />
    DataContext=
    "(Binding ElementName=orderSelector, Path=SelectedItem)"
    ItemsSource="(Binding XPath=orderDetail)">



    Προϊόν:

    (

    )





    Σημειώστε την εκτεταμένη χρήση σύντομων ερωτημάτων XPath για να υποδείξετε το WPF στο σημείο ανάκτησης των δεσμευμένων τιμών. Η κλάση Binding παρέχει μια ιδιότητα XPath που μπορεί να εκχωρηθεί σε οποιοδήποτε ερώτημα XPath που υποστηρίζεται από τη μέθοδο XmlNode.SelectNodes. Τα εσωτερικά WPF χρησιμοποιούν αυτήν τη μέθοδο για την εκτέλεση ερωτημάτων XPath. Δυστυχώς, αυτό σημαίνει ότι εφόσον το XmlNode.SelectNodes δεν υποστηρίζει αυτήν τη στιγμή τη χρήση των συναρτήσεων XPath, η σύνδεση δεδομένων WPF δεν τις υποστηρίζει.

    Το πλαίσιο λίστας πελατών και η λίστα παραγγελιών συνδέονται με το προκύπτον σύνολο κόμβων ερωτήματος XPath που εκτελούνται από το ερώτημα DataContext του στοιχείου ρίζας Grid. Το DataContext της λίστας θα επιστρέψει αυτόματα το CurrentItem της προβολής συλλογής, το οποίο είναι ένα περιτύλιγμα για τη συλλογή XmlNodes που δημιουργήθηκε για το DataContext του πίνακα. Με άλλα λόγια, το DataContext της λίστας είναι αυτό που επιλέγεται παρούσα στιγμήπελάτης. Επειδή το ItemsSource της λίστας είναι έμμεσα συνδεδεμένο με το δικό του DataContext (επειδή δεν καθορίστηκε άλλη πηγή) και η δέσμευσή του ItemsSource εκτελεί ένα ερώτημα XPath για την ανάκτηση των στοιχείων από το DataContext, τότε το ItemsSource δεσμεύεται στη λίστα με τις παραγγελίες του επιλεγμένου πελάτη.

    Θυμηθείτε ότι όταν δεσμεύεστε σε δεδομένα XML, η πραγματική σύνδεση είναι στα αντικείμενα που δημιουργούνται από την κλήση στο XmlNode.SelectNodes. Εάν δεν είστε προσεκτικοί, μπορείτε να καταλήξετε με πολλά στοιχεία ελέγχου που συνδέονται με λογικά ισοδύναμα αλλά φυσικά διαφορετικά σύνολα XmlNodes. Αυτό συμβαίνει επειδή κάθε φορά που καλείτε το XmlNode.SelectNodes, α νέο σετ XmlNode, ακόμα κι αν στέλνετε το ίδιο ερώτημα XPath στο ίδιο XmlNode κάθε φορά. Αυτό ειδικό πρόβλημασύνδεση με δεδομένα XML, ώστε να μπορείτε να τα αγνοήσετε με ασφάλεια όταν δεσμεύεστε σε επιχειρηματικά αντικείμενα.

    Χρήση πολλαπλών στοιχείων ελέγχου για την εμφάνιση επιχειρηματικών αντικειμένων

    Τώρα ας υποθέσουμε ότι θέλετε να συνδεθείτε με τα δεδομένα από το προηγούμενο παράδειγμα, αλλά τα δεδομένα υπάρχουν ως επιχειρηματικά αντικείμενα και όχι σε κώδικα XML. Πώς θα αλλάξει αυτό τον τρόπο με τον οποίο δεσμευόμαστε σε διαφορετικά επίπεδα της ιεραρχίας δεδομένων; Πόσο παρόμοια ή διαφορετική θα είναι η υποδοχή;

    Στον κώδικα στο Σχ. Το σχήμα 7 δείχνει τις απλές κλάσεις που χρησιμοποιούνται για τη δημιουργία επιχειρηματικών αντικειμένων που αποθηκεύουν τα δεδομένα που θα δεσμευτούν. Αυτές οι τάξεις αποτελούν το ίδιο λογικό κύκλωμα, το ίδιο με τα δεδομένα XML που χρησιμοποιήθηκαν στην προηγούμενη ενότητα.

    Ρύζι. 7. Τάξεις για τη δημιουργία ιεραρχίας επιχειρηματικών αντικειμένων

    Πελάτης δημόσιας κατηγορίας
    {
    Όνομα δημόσιας συμβολοσειράς (get; set;)
    δημόσια λίστα Παραγγελίες (λήψη; ορισμός;)


    {
    επιστρέψτε αυτό.Όνομα;
    }
    }

    Παραγγελία δημόσιας τάξης
    {
    δημόσια συμβολοσειρά Desc ( get; set; )
    δημόσια λίστα Στοιχεία παραγγελίας (λήψη; ορισμός;)

    δημόσια παράκαμψη συμβολοσειράς ToString()
    {
    επιστρέψτε αυτό.Περιγραφή?
    }
    }

    δημόσια τάξη OrderDetail
    {
    Προϊόν δημόσιας συμβολοσειράς ( get; set; )
    public int Ποσότητα ( get; set; )
    }

    Ο κώδικας XAML για το παράθυρο που εμφανίζει αυτά τα αντικείμενα φαίνεται στην Εικ. 8. Μοιάζει πολύ με τον κώδικα XAML στο Σχ. 6, αλλά υπάρχουν μεταξύ τους σημαντικές διαφορές, που αξίζει να προσέξετε. Αυτό που δεν βλέπει ο κώδικας XAML είναι ένας κατασκευαστής παραθύρου που δημιουργεί αντικείμενα δεδομένων και ορίζει το DataContext, αντί ο κώδικας XAML να ορίζει μια αναφορά σε αυτό ως πόρο. Σημειώστε ότι σε κανένα από τα στοιχεία ελέγχου δεν έχει οριστεί απευθείας η ιδιότητα DataContext. Όλα κληρονομούν την ίδια ιδιότητα DataContext, η οποία είναι μια παρουσία λίστας .

    Ρύζι. 8. Κώδικας XAML για τη σύνδεση ιεραρχικών επιχειρηματικών αντικειμένων στη διεπαφή χρήστη








    />
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="(Binding Path=.)"
    />




    IsSynchronizedWithCurrentItem="True"
    ItemsSource="(Binding Path=CurrentItem.Orders)"
    />



    Text="Λεπτομέρειες παραγγελίας" />
    ItemsSource="(Binding Path=CurrentItem.Orders.CurrentItem.
    Στοιχεία παραγγελίας)"
    >



    Προϊόν:

    (

    )





    Μια άλλη σημαντική διαφορά κατά τη σύνδεση σε επιχειρηματικά αντικείμενα αντί για XML είναι ότι το ItemsControl που διατηρεί τις πληροφορίες παραγγελίας δεν χρειάζεται να συνδεθεί με το SelectedItem της λίστας παραγγελιών. Αυτή η προσέγγιση ήταν απαραίτητη στην περίπτωση της σύνδεσης XML λόγω της έλλειψης καθολικού τρόπου αναφοράς στο τρέχον στοιχείο μιας λίστας, τα στοιχεία της οποίας προέρχονται από ένα τοπικό ερώτημα XPath.

    Κατά τη σύνδεση σε επιχειρηματικά αντικείμενα αντί για XML, η σύνδεση σε ένθετα επίπεδα επιλεγμένων στοιχείων είναι μια ασήμαντη εργασία. Η δέσμευση ItemsSource του ItemsControl χρησιμοποιεί αυτό βολική λειτουργία, προσδιορίζοντας το CurrentItem δύο φορές στη διαδρομή δέσμευσης: μία για τον επιλεγμένο πελάτη, μία για την επιλεγμένη παραγγελία. Η ιδιότητα CurrentItem είναι μέλος του υποκείμενου ICollectionView, το οποίο αναδιπλώνει την προέλευση δεδομένων, όπως συζητήθηκε παραπάνω.

    Υπάρχει άλλο ένα ενδιαφέρον σημείο, αναφερόμενος στη διαφορά στον τρόπο λειτουργίας της XML και ενός επιχειρηματικού αντικειμένου. Επειδή το παράδειγμα XML συνδέεται με το XmlElements, πρέπει να παρέχετε DataTemplates για να εξηγήσετε πώς να οπτικοποιήσετε πελάτες και παραγγελίες. Όταν δεσμεύετε σε προσαρμοσμένα επιχειρηματικά αντικείμενα, μπορείτε να αποφύγετε αυτήν την επιπλέον εργασία παρακάμπτοντας απλώς τη μέθοδο ToString των κλάσεων Customer and Order και αφήνοντας το WPF να εμφανίζει την έξοδο αυτής της μεθόδου για αυτά τα αντικείμενα. Αυτό το τέχνασμα είναι αρκετό μόνο για αντικείμενα που μπορούν να έχουν απλές αναπαραστάσεις κειμένου. Όταν εργάζεστε με σύνθετα αντικείμενα δεδομένων, η χρήση αυτής της τεχνικής ευκολίας μπορεί να μην έχει νόημα.

    Ένα στοιχείο ελέγχου για την εμφάνιση ολόκληρης της ιεραρχίας

    Να αυτή τη στιγμήΈδειχνε μόνο τρόπους εμφάνισης ιεραρχικών δεδομένων εμφανίζοντας κάθε επίπεδο της ιεραρχίας σε ξεχωριστά στοιχεία ελέγχου. Είναι συχνά χρήσιμο και απαραίτητο να επιδεικνύονται όλα τα επίπεδα μιας ιεραρχικής δομής δεδομένων σε ένα μόνο στοιχείο ελέγχου. Το κανονικό παράδειγμα αυτής της προσέγγισης είναι το στοιχείο ελέγχου TreeView, το οποίο υποστηρίζει την εμφάνιση και την επανάληψη μέσω ενός αυθαίρετου αριθμού επιπέδων ένθετων δεδομένων.

    Μπορείτε να συμπληρώσετε ένα TreeView στο WPF με στοιχεία με έναν από τους δύο τρόπους. Ο πρώτος τρόπος είναι να προσθέσετε στοιχεία με μη αυτόματο τρόπο σε κώδικα ή σε XAML και ο δεύτερος είναι να τα δημιουργήσετε μέσω σύνδεσης δεδομένων.

    Το ακόλουθο XAML δείχνει πώς μπορείτε να προσθέσετε TreeViewItems σε ένα TreeView στο XAML:







    Η τεχνική της μη αυτόματης δημιουργίας στοιχείων σε ένα TreeView έχει νόημα σε περιπτώσεις όπου το στοιχείο ελέγχου θα εμφανίζει πάντα ένα μικρό και στατικό σύνολο στοιχείων. Όταν υπάρχει ανάγκη εμφάνισης μεγάλων ποσοτήτων δεδομένων που μπορεί να αλλάξουν με την πάροδο του χρόνου, καθίσταται απαραίτητη μια πιο δυναμική προσέγγιση. Σε αυτό το στάδιο υπάρχουν δύο επιλογές. Μπορείτε να γράψετε κώδικα που διασχίζει τη δομή δεδομένων, να δημιουργεί TreeViewItems με βάση τα αντικείμενα δεδομένων που βρίσκει και να προσθέτει αυτά τα στοιχεία στο TreeView. Μια εναλλακτική είναι να χρησιμοποιήσετε ιεραρχικά πρότυπα δεδομένων και να αφήσετε όλη την εργασία στο WPF.

    Χρήση προτύπων ιεραρχικών δεδομένων

    Ο τρόπος με τον οποίο το WPF πρέπει να οπτικοποιεί τα ιεραρχικά δεδομένα μέσω ιεραρχικών προτύπων δεδομένων μπορεί να εκφραστεί με δηλωτικό τρόπο. Η κλάση HierarchicalDataTemplate είναι ένα εργαλείο που γεφυρώνει το χάσμα μεταξύ μιας σύνθετης δομής δεδομένων και μιας οπτικής αναπαράστασης αυτών των δεδομένων. Είναι πολύ παρόμοιο με ένα κανονικό DataTemplate, αλλά σας επιτρέπει επίσης να καθορίσετε από πού προέρχονται τα παιδιά του αντικειμένου δεδομένων. Μπορείτε επίσης να παρέχετε στην τάξη HierarchicalDataTemplate ένα πρότυπο για την απόδοση αυτών των παιδιών.

    Ας υποθέσουμε ότι τώρα θέλουμε να εμφανίσουμε τα δεδομένα που φαίνονται στο Σχ. 7 μέσα σε ένα στοιχείο ελέγχου TreeView. Το TreeView που προκύπτει μπορεί να μοιάζει με αυτό που φαίνεται στο Σχ. 9. Η εφαρμογή αυτού περιλαμβάνει τη χρήση δύο HierarchicalDataTemplates και ενός DataTemplate.

    Ρύζι. 9. Εμφάνιση μιας ολόκληρης ιεραρχίας δεδομένων σε ένα TreeView

    Δύο ιεραρχικά πρότυπα εμφανίζουν αντικείμενα Πελάτη και Παραγγελίας. Επειδή τα αντικείμενα OrderDetail δεν έχουν θυγατρικά, μπορούν να αποδοθούν χρησιμοποιώντας ένα μη ιεραρχικό DataTemplate. Η ιδιότητα ItemTemplate του TreeView χρησιμοποιεί ένα πρότυπο για αντικείμενα πελάτη, επειδή τα αντικείμενα πελάτη και τα αντικείμενα δεδομένων περιέχονται στο ριζικό επίπεδο του TreeView. Στον κώδικα XAML που φαίνεται στο Σχ. Το σχήμα 10 δείχνει πώς ενώνονται όλα τα κομμάτια αυτού του παζλ.

    Ρύζι. 10. XAML πίσω από το TreeView




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





    Προϊόν:

    (

    )


    x:Key="Πρότυπο παραγγελίας"
    ItemsSource="(Binding Path=OrderDetails)"
    ItemTemplate="(StaticResource OrderDetailTemplate)"
    >


    x:Key="CustomerTemplate"
    ItemsSource="(Binding Path=Orders)"
    ItemTemplate="(StaticResource OrderTemplate)"
    >


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

    Εκχωρώ μια συλλογή αντικειμένων πελάτη στο DataContext ενός πίνακα (Grid) που περιέχει ένα TreeView. Στον κώδικα XAML, αυτό μπορεί να γίνει χρησιμοποιώντας το ObjectDataProvider, το οποίο είναι με βολικό τρόποκαλώντας μια μέθοδο από το XAML. Επειδή το DataContext κληρονομείται στο δέντρο στοιχείων, το DataContext του TreeView παρέχει μια αναφορά σε αυτό το σύνολο αντικειμένων πελάτη. Για αυτόν τον λόγο μπορούμε να δώσουμε στην ιδιότητά ItemsSource μια δέσμευση "(Binding Path=.)", που είναι ένας τρόπος να υποδείξουμε ότι η ιδιότητα ItemsSource είναι δεσμευμένη στο DataContext του TreeView.

    Εάν δεν έχει οριστεί η ιδιότητα ItemTemplate του TreeView, το TreeView θα εμφανίζει μόνο τα αντικείμενα πελάτη ανώτατου επιπέδου. Εφόσον το WPF δεν γνωρίζει πώς να αποδίδει έναν πελάτη, θα καλεί το ToString σε κάθε πελάτη και θα εμφανίζει αυτό το κείμενο για κάθε στοιχείο. Δεν θα έχει κανέναν τρόπο να καταλάβει ότι κάθε Πελάτης έχει μια λίστα αντικειμένων Παραγγελίας που σχετίζονται με αυτόν και κάθε αντικείμενο Παραγγελίας έχει μια λίστα με αντικείμενα OrderDetail. Επειδή το WPF δεν μπορεί να κατανοήσει ως δια μαγείας ένα υπάρχον σχήμα δεδομένων, είναι απαραίτητο να εξηγηθεί το σχήμα στο WPF, ώστε να μπορεί να απεικονίσει σωστά τη δομή δεδομένων.

    Τα HierarchicalDataTemplates μπαίνουν στο παιχνίδι όταν χρειάζεται να εξηγήσετε τη δομή και την εμφάνιση των δεδομένων στο WPF. Τα πρότυπα που χρησιμοποιούνται σε αυτήν την επίδειξη περιέχουν πολύ απλά οπτικά δέντρα, βασικά μόνο πεδία TextBlock με μικρή ποσότητα κειμένου σε αυτά. Σε πιο εξελιγμένες εφαρμογές, τα πρότυπα μπορεί να έχουν διαδραστικά περιστρεφόμενα τρισδιάστατα μοντέλα, εικόνες, σχέδια διανυσματικά γραφικά, πολύπλοκα UserControls ή οποιοδήποτε άλλο περιεχόμενο WPF που έχει σχεδιαστεί για την απόδοση ενός υποκείμενου αντικειμένου δεδομένων.

    Είναι σημαντικό να προσέχετε τη σειρά με την οποία δηλώνονται τα πρότυπα. Ένα πρότυπο πρέπει να δηλωθεί για να είναι δυνατή η αναφορά του μέσω μιας έκφρασης StaticResource. Αυτή είναι μια απαίτηση που επιβάλλεται από το πρόγραμμα ανάγνωσης XAML και ισχύει για όλους τους πόρους, όχι μόνο για τα πρότυπα.

    Αντίθετα, τα πρότυπα μπορούν να αναφέρονται χρησιμοποιώντας μια έκφραση DynamicResource, σε αυτήν την περίπτωση, η λεξική σειρά των δηλώσεων προτύπων δεν είναι σημαντική. Ωστόσο, η χρήση συνδέσμων DynamicResource, σε αντίθεση με τους συνδέσμους StaticResource, συνοδεύεται από κάποια επιβάρυνση εκτέλεσης επειδή παρακολουθούν αλλαγές στο σύστημα πόρων. Δεδομένου ότι δεν αντικαθιστούμε πρότυπα κατά την εκτέλεση, αυτό το γενικό κόστος είναι περιττό, επομένως είναι καλύτερο να χρησιμοποιείτε αναφορές StaticResource και να τοποθετείτε τις δηλώσεις προτύπων με τη σωστή σειρά.

    Εργασία με την εισαγωγή χρήστη

    Για τα περισσότερα προγράμματα, η εμφάνιση δεδομένων είναι μόνο η μισή μάχη. Μια άλλη σημαντική πρόκληση είναι η ανάλυση, η αποδοχή και η απόρριψη της εισόδου χρήστη. Σε έναν ιδανικό κόσμο όπου όλοι οι χρήστες εισάγουν πάντα λογικά και ακριβή δεδομένα, αυτό θα ήταν μια απλή εργασία. Αλλά στον πραγματικό κόσμο αυτό δεν συμβαίνει. Οι πραγματικοί χρήστες κάνουν τυπογραφικά λάθη, ξεχνούν να εισάγουν τις απαιτούμενες τιμές, εισάγουν τιμές σε λάθος σημεία, σβήνουν καταχωρήσεις που δεν πρέπει να διαγράφονται, προσθέτουν εγγραφές που δεν πρέπει να προστίθενται και γενικά ακολουθούν τον νόμο του Μέρφι όποτε είναι δυνατόν.

    Η δουλειά μας ως προγραμματιστές και αρχιτέκτονες είναι να καταπολεμήσουμε αυτό που αναπόφευκτα θα εισέλθουν οι χρήστες κατά λάθος ή κακόβουλη πρόθεση. Υποδομή Δεσμεύσεις WPFυποστηρίζει επικύρωση εισόδου. Στις επόμενες ενότητες αυτού του άρθρου, θα εξηγήσω πώς να χρησιμοποιήσετε την υποστήριξη επικύρωσης του WPF, καθώς και πώς να εμφανίσετε μηνύματα σφάλματος στον χρήστη όταν εντοπίζονται σφάλματα επικύρωσης.

    Επικύρωση εισόδου μέσω ValidationRules

    Η πρώτη έκδοση του WPF, η οποία ήταν μέρος του Microsoft® .NET Framework 3.0, είχε περιορισμένη υποστήριξη για επικύρωση εισόδου. Η κλάση Binding είχε μια ιδιότητα ValidationRules που μπορούσε να αποθηκεύσει οποιονδήποτε αριθμό κλάσεων που προέρχονται από το ValidationRule. Κάθε ένας από αυτούς τους κανόνες θα μπορούσε να περιέχει κάποια λογική που ελέγχει εάν η δεσμευμένη τιμή είναι έγκυρη.

    Εκείνη την εποχή, το WPF είχε μόνο μια υποκλάση ValidationRule που ονομάζεται ExceptionValidationRule. Οι προγραμματιστές θα μπορούσαν να προσθέσουν αυτόν τον κανόνα στην ιδιότητα ValidationRules μιας σύνδεσης, η οποία στη συνέχεια θα συλλάβει τις εξαιρέσεις που δημιουργούνται κατά τις ενημερώσεις στην πηγή δεδομένων, επιτρέποντας στη διεπαφή χρήστη να εμφανίζει ένα μήνυμα σφάλματος εξαίρεσης. Η χρησιμότητα αυτής της προσέγγισης για την επικύρωση των εισροών είναι αμφισβητήσιμη, δεδομένου ότι η βάση μιας καλής εμπειρίας χρήστη είναι να αποφευχθεί η έκθεσή τους σε περιττές τεχνικές λεπτομέρειες. Τα μηνύματα σφάλματος στις εξαιρέσεις ανάλυσης δεδομένων είναι συνήθως τέτοιες λεπτομέρειες για τους περισσότερους χρήστες, αλλά πίσω στο θέμα μας.

    Ας υποθέσουμε ότι έχουμε μια τάξη που αντιπροσωπεύει μια εποχή του χρόνου, όπως η απλή κλάση Era που εμφανίζεται εδώ:

    Εποχή δημόσιας τάξης
    {

    }

    Εάν θέλετε να επιτρέψετε στον χρήστη να αλλάξει την ημερομηνία έναρξης και τη διάρκεια μιας εποχής, μπορείτε να χρησιμοποιήσετε δύο στοιχεία ελέγχου πλαισίου κειμένου και να συνδέσετε τις ιδιότητες κειμένου τους με τις ιδιότητες της παρουσίας Era. Επειδή ο χρήστης μπορεί να εισάγει ό,τι θέλει σε ένα πεδίο κειμένου, δεν υπάρχει τρόπος να είναι σίγουρος ότι το κείμενο που εισάγει θα μπορεί να μετατραπεί σε μια παρουσία DateTime ή TimeSpan. Σε αυτήν την περίπτωση, μπορείτε να χρησιμοποιήσετε το ExceptionValidationRule για να αναφέρετε σφάλματα στο μετασχηματισμό δεδομένων και, στη συνέχεια, να εμφανίσετε αυτά τα σφάλματα στη διεπαφή χρήστη. Στον κώδικα XAML που φαίνεται στο Σχ. Το Σχήμα 11 δείχνει πώς μπορεί να επιτευχθεί αυτή η εργασία.

    Ρύζι. 11. Μια απλή τάξη που αντιπροσωπεύει μια χρονική εποχή


    Ημερομηνία έναρξης:









    Διάρκεια:
    Grid.Row="3"
    Text="(Δεσμ
    Διαδρομή=Διάρκεια,

    />

    Αυτά τα δύο πεδία κειμένου δείχνουν δύο τρόπους με τους οποίους μπορεί να προστεθεί ένας ExceptionValidationRule στην ιδιότητα ValidationRules μιας σύνδεσης στο XAML. Το πλαίσιο κειμένου Ημερομηνία έναρξης χρησιμοποιεί εκτεταμένη σύνταξη στοιχείων ιδιότητας για την απευθείας προσθήκη ενός κανόνα. Το πλαίσιο κειμένου Διάρκεια χρησιμοποιεί μια σύντομη σύνταξη που απλώς ορίζει την ιδιότητα σύνδεσης ValidatesOnExceptions σε true. Και οι δύο δεσμεύσεις έχουν την ιδιότητα UpdateSourceTrigger που έχει οριστεί σε PropertyChanged, έτσι ώστε η είσοδος να ελέγχεται κάθε φορά που δίνεται νέα τιμή στην ιδιότητα Κείμενο του πεδίου κειμένου, αντί να περιμένουμε μέχρι το στοιχείο ελέγχου να χάσει την εστίαση. Ένα στιγμιότυπο οθόνης του προγράμματος φαίνεται στο Σχ. 12.

    Ρύζι. 12. ExceptionValidationRule εμφανίζει σφάλματα επικύρωσης

    Εμφάνιση σφαλμάτων επικύρωσης

    Όπως φαίνεται στο Σχ. 13, το πλαίσιο κειμένου Διάρκεια περιέχει μια εσφαλμένη τιμή. Η συμβολοσειρά που περιέχει δεν είναι μετατρέψιμη σε στιγμιότυπο TimeSpan. Το μήνυμα τοστ του πλαισίου κειμένου εμφανίζει ένα μήνυμα σφάλματος και ένα μικρό κόκκινο εικονίδιο σφάλματος εμφανίζεται στη δεξιά πλευρά του στοιχείου ελέγχου. Αυτή η συμπεριφορά δεν είναι αυτόματη, αλλά είναι εύκολο να εφαρμοστεί και να προσαρμοστεί σε μια συγκεκριμένη περίπτωση.

    Ρύζι. 13. Οπτικοποίηση σφαλμάτων που εντοπίστηκαν κατά την επαλήθευση εισόδου για τον χρήστη




    DockPanel.Dock="Δεξιά"
    Περιθώριο = "2.0"
    ToolTip="Περιέχει μη έγκυρα δεδομένα"
    Πλάτος = "10" Ύψος = "10"
    >











    Η κλάση Static Validation σχηματίζει τη σχέση μεταξύ του στοιχείου ελέγχου και τυχόν σφαλμάτων επικύρωσης που περιέχει μέσω της χρήσης συνημμένων ιδιοτήτων και στατικών μεθόδων. Αυτές οι συνημμένες ιδιότητες μπορούν να αναφέρονται στο XAML για τη δημιουργία περιγραφών μονής σήμανσης σχετικά με τον τρόπο με τον οποίο η διεπαφή χρήστη θα πρέπει να παρουσιάζει στον χρήστη σφάλματα που παρουσιάζονται κατά την επικύρωση εισόδου. Ο κώδικας XAML στο Σχ. Το 13 είναι υπεύθυνο για την εξήγηση του τρόπου απόδοσης μηνυμάτων σφάλματος εισόδου για τα δύο στοιχεία ελέγχου πλαισίου κειμένου από το προηγούμενο παράδειγμα.

    Στυλ ("Στυλ") στο Σχ. 13 στοχεύει όλες τις εμφανίσεις ενός πεδίου κειμένου στη διεπαφή χρήστη Εφαρμόζει τρεις παραμέτρους στο πεδίο κειμένου. Το πρώτο, Setter, επηρεάζει την ιδιότητα Margin του πεδίου κειμένου. Η ιδιότητα Margin έχει οριστεί σε μια τιμή που παρέχει αρκετό χώρο για να εμφανιστεί το εικονίδιο σφάλματος στη δεξιά πλευρά.

    Η ακόλουθη ιδιότητα Setter στο Style εκχωρεί το ControlTemplate που χρησιμοποιείται για την απόδοση του πεδίου κειμένου όταν περιέχει μη έγκυρα δεδομένα. Ορίζει τη συνημμένη ιδιότητα Validation.ErrorTemplate στο ControlTemplate που δηλώνεται πάνω από το Στυλ. Όταν η κλάση επικύρωση αναφέρει ότι η επικύρωση έχει εντοπίσει ένα ή περισσότερα σφάλματα σε ένα πεδίο κειμένου, το πεδίο κειμένου αποδίδει το μήνυμα χρησιμοποιώντας αυτό το πρότυπο. Αυτό είναι που δημιουργεί το κόκκινο εικονίδιο σφάλματος που φαίνεται στην Εικόνα. 12.

    Το στυλ περιέχει επίσης ένα Trigger που παρακολουθεί την ιδιότητα Validation.HasError που είναι συνδεδεμένη στο πεδίο κειμένου. Όταν η κλάση Validation ορίζει τη συνημμένη ιδιότητα HasError σε αληθή για ένα συγκεκριμένο πεδίο κειμένου, ενεργοποιείται το Trigger in the Style και εκχωρεί ένα μήνυμα φρυγανιάς στο πεδίο κειμένου. Το περιεχόμενο του μηνύματος τοστ συνδέεται με το μήνυμα σφάλματος της εξαίρεσης που εμφανίζεται κατά την προσπάθεια μετατροπής κειμένου από ένα πλαίσιο κειμένου σε μια παρουσία του τύπου δεδομένων της ιδιότητας προέλευσης δεδομένων.

    Επικύρωση εισαγωγής μέσω IDataErrorInfo

    Με την κυκλοφορία του Microsoft .NET Framework 3.5, η υποστήριξη για επικύρωση εισόδου στο WPF έχει βελτιωθεί δραματικά. Η προσέγγιση ValidationRule είναι χρήσιμη για απλές εφαρμογές, αλλά οι εφαρμογές πραγματικού κόσμου αντιμετωπίζουν την πολυπλοκότητα των πραγματικών δεδομένων και των επιχειρηματικών κανόνων. Η κωδικοποίηση επιχειρηματικών κανόνων σε αντικείμενα ValidationRule όχι μόνο συνδέει αυτόν τον κώδικα με το πλαίσιο WPF, αλλά επίσης εμποδίζει την επιχειρηματική λογική να βρίσκεται εκεί που ανήκει: σε επιχειρηματικά αντικείμενα!

    Πολλές εφαρμογές έχουν ένα επιχειρηματικό επίπεδο, όπου όλη η πολυπλοκότητα της επεξεργασίας των επιχειρηματικών κανόνων περιέχεται σε ένα σύνολο επιχειρηματικών αντικειμένων. Όταν γίνεται μεταγλώττιση στο Microsoft .NET Framework 3.5, μπορείτε να χρησιμοποιήσετε τη διεπαφή IDataErrorInfo για να αναγκάσετε το WPF να υποβάλει ερωτήματα στα επιχειρηματικά αντικείμενα είτε βρίσκονται σε έγκυρη κατάσταση είτε όχι. Αυτό εξαλείφει την ανάγκη τοποθέτησης επιχειρηματικής λογικής σε αντικείμενα ξεχωριστά από το επιχειρηματικό επίπεδο και σας επιτρέπει να δημιουργείτε επιχειρηματικά αντικείμενα που είναι ανεξάρτητα από την πλατφόρμα διεπαφής χρήστη. Επειδή η διεπαφή IDataErrorInfo χρησιμοποιείται εδώ και αρκετά χρόνια, διευκολύνει επίσης την επαναχρησιμοποίηση επιχειρηματικών αντικειμένων από παλαιότερες φόρμες των Windows ή εφαρμογές ASP.NET.

    Ας υποθέσουμε ότι θέλετε να παράσχετε επικύρωση για μια εποχή που υπερβαίνει την απλή διασφάλιση ότι το κείμενο που παρέχεται από τον χρήστη είναι μετατρέψιμο στον τύπο δεδομένων μιας ιδιότητας πηγής δεδομένων. Μπορεί να έχει νόημα να μην τοποθετήσουμε την ημερομηνία έναρξης μιας εποχής στο μέλλον, αφού δεν γνωρίζουμε για εποχές που έρχονται. Η απαίτηση ότι η εποχή διαρκεί τουλάχιστον ένα χιλιοστό του δευτερολέπτου μπορεί επίσης να έχει νόημα.

    Αυτοί οι τύποι κανόνων είναι παρόμοιοι με τη γενική ιδέα της επιχειρηματικής λογικής στο ότι είναι και οι δύο περιπτώσεις κανόνων πεδίου εφαρμογής. Οι κανόνες εμβέλειας δημιουργούνται καλύτερα σε αντικείμενα που αποθηκεύουν την κατάστασή τους: αντικείμενα εμβέλειας. Στον κώδικα που φαίνεται στο Σχ. 14 δείχνει την κλάση SmartEra, η οποία παρέχει μηνύματα σχετικά με σφάλματα που εντοπίστηκαν από τον έλεγχο μέσω της διεπαφής IDataErrorInfo.

    Ρύζι. 14. Το IDataErrorInfo παρέχει μηνύματα σχετικά με σφάλματα που εντοπίστηκαν από τον έλεγχο

    δημόσια τάξη SmartEra
    : System.ComponentModel.IDataErrorInfo
    {
    δημόσια Ημερομηνία Ώρα Έναρξης Ημερομηνία ( λήψη; ορισμός; )
    δημόσια Χρονική Διάρκεια (λήψη; ορισμός;)

    #region IDataErrorInfo Μέλη

    Σφάλμα δημόσιας συμβολοσειράς
    {
    παίρνω (επιστρέφω μηδενική; )
    }

    δημόσια συμβολοσειρά αυτό
    {
    παίρνω
    {
    string msg = null;
    διακόπτης (ιδιότητα)
    {
    υπόθεση "StartDate":
    εάν (Ημερομηνία Ώρα. Τώρα< this.StartDate)
    msg = "Η ημερομηνία έναρξης πρέπει να είναι στο παρελθόν.";
    διακοπή;

    υπόθεση "Διάρκεια":
    αν (αυτό.Διάρκεια.Τσιμπούρια == 0)
    msg = "Μια εποχή πρέπει να έχει διάρκεια.";
    διακοπή;

    αθέτηση:
    ρίχνω νέο ArgumentException(
    "Μη αναγνωρισμένη ιδιοκτησία: " + ιδιοκτησία);
    }
    επιστροφή μηνύματος;
    }
    }

    #endregion // IDataErrorInfo Μέλη
    }

    Η χρήση της υποστήριξης επικύρωσης κλάσης SmartEra από τη διεπαφή χρήστη του WPF είναι πολύ εύκολη. Απλώς πρέπει να πείτε στους συνδέσμους ότι θα πρέπει να αποδέχονται τη διεπαφή IDataErrorInfo στο αντικείμενο στο οποίο συνδέονται. Αυτό μπορεί να γίνει με έναν από τους δύο τρόπους, όπως φαίνεται στο Σχ. 15.

    Ρύζι. 15. Χρήση λογικής επικύρωσης


    Ημερομηνία έναρξης:










    Διάρκεια:
    Grid.Row="3"
    Text="(Δεσμ
    Διαδρομή=Διάρκεια,
    UpdateSourceTrigger=PropertyChanged,
    ValidatesOnDataErrors=True,
    ValidatesOnExceptions=True)"
    />

    Ακριβώς όπως ένας ExceptionValidationRule μπορεί να προστεθεί στη συλλογή ValidationRules ενός binding είτε ρητά είτε έμμεσα, ένας DataErrorValidationRule μπορεί να προστεθεί απευθείας στους ValidationRules ενός binding ή η ιδιότητα ValidatesOnDataErrors μπορεί να οριστεί σε true. Και οι δύο προσεγγίσεις έχουν το ίδιο τελικό αποτέλεσμα - το δεσμευτικό σύστημα ρωτά τη διεπαφή IDataErrorInfo της πηγής δεδομένων για σφάλματα που εντοπίζονται από τον έλεγχο.

    Ανακεφαλαίωση

    Υπάρχει ένας λόγος που πολλοί προγραμματιστές λένε ότι η αγαπημένη τους δυνατότητα WPF είναι η εκτεταμένη υποστήριξή του για δέσμευση δεδομένων. Οι δυνατότητες σύνδεσης του WPF είναι τόσο ισχυρές και διάχυτες που απαιτούν από πολλούς προγραμματιστές λογισμικού να προσαρμόσουν τον τρόπο που σκέφτονται για τη σχέση μεταξύ δεδομένων και της διεπαφής χρήστη. Πολλά βασικά στοιχεία του WPF συνεργάζονται για να υποστηρίξουν περίπλοκες περιπτώσεις δέσμευσης δεδομένων, όπως πρότυπα, στυλ και συνημμένες ιδιότητες.

    Με σχετικά λίγες γραμμές κώδικα XAML, μπορείτε να εκφράσετε τις προθέσεις σας για την εμφάνιση μιας ιεραρχικής δομής δεδομένων και την επικύρωση των εισροών χρήστη. Σε πιο περίπλοκες καταστάσεις, μπορείτε να επωφεληθείτε από όλες τις δυνατότητες του συστήματος δέσμευσης, προσβαίνοντας σε αυτό μέσω προγραμματισμού. Με μια τόσο ισχυρή υποδομή στη διάθεσή τους, οι προγραμματιστές που κατασκευάζουν σύγχρονες επιχειρηματικές εφαρμογές μπορούν επιτέλους να φτάσουν κοντά στην επίτευξη του αρχαίου στόχου τους να προσφέρουν εξαιρετικές εμπειρίες χρήστη και συναρπαστικές απεικονίσεις δεδομένων.