Laden...

[gelöst] BindingSource und DataBindings

Erstellt von syn87 vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.161 Views
S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren
[gelöst] BindingSource und DataBindings

Hallo zusammen,

ich habe ein Objekt der Klasse Person, welches ich an verschiedene GUI Textboxen, etc. per DataBindings binde. Dabei soll die eingabe automatisch formatiert werden. Für ein Property benutze ich daher eine Funktion die ungefaehr so aussieht:

SetValue(ref string oldVal, string newVal, FormatType formatting)

Die FormatTypes umfassen dabei z.b. Uppercase, Lowercase, PhoneNumber etc.

Das Problem ist, dass die GUI vom formatieren nichts mitbekommt und weiterhin der unformatierte Text drin steht. Mach ich irgendetwas falsch?

LG

Matze

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo syn87,

was tut SetValue und wo landet der formatierte Wert dann?

herbivore

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Hallo herbivore,

SetValue macht folgendes:


            if (oldValue != null && oldValue.Equals(newValue)) return;

            OnPropertyChanging(propertyName);

            newValue = Format(newValue, CharacterCasing.Capitalize);

            oldValue = newValue;

            Validate(this.GetType().GetProperty(propertyName));

            OnPropertyChanged(propertyName);

Die Value wird soweit korrekt gesetzt, aber die GUI aktualisiert sich wie gesagt nicht. Gerade hab ich im Dialog fuer ein Binding noch die Möglichkeit gefunden, es auf OnPropertyChanged zu stellen, allerdings ohne Wirkung.

Nur um Mißverstaendnisse zu beseitigen: Ich benutze ein BindingSource mit dem Typ Person als DataSource, und die GUI Elemente binden sich dann an den BindingSource. Ist das so gängig? Früher hatte ich es anders gemacht, ueber [textbox].DataBindings.Add(....), dachte dann aber, dass die andere Variante besser ist.

Gruß

U
36 Beiträge seit 2008
vor 14 Jahren

Hallo syn87,

müßte es nicht heißen :

newValue = Format(oldValue, CharacterCasing.Capitalize); ?

Gruß

Michael Schmitz

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Naja es dürfte ja egal sein, ob ich den neuen Wert zuerst formatiere und dann auf den Ref schreibe, oder erst setze und dann formatiere.

LG

edit:

Gut, ohne dass ich die Signatur poste, ist das etwas verwirrend:

protected void SetPropertyValue(string propertyName, ref string oldValue, string newValue)

==============================

Ich habe gerade gelesen, dass eine Formatierung in der Business Schicht, wie ich es ja vorhabe, nicht möglich sei, und ich stattdessen innerhalb der GUI formatieren muesste. Kann das jemand bestätigen?

5.299 Beiträge seit 2008
vor 14 Jahren

Ich habe gerade gelesen, dass eine Formatierung in der Business Schicht, wie ich es ja vorhabe, nicht möglich sei, und ich stattdessen innerhalb der GUI formatieren muesste. Kann das jemand bestätigen?

Ich kann nur sagen, prinzipiell denke ich auch so. (nur lasssich gelegentlich auch mal 5e grade sein).
Ist doch logisch, Formatierung ist klar Sache der Anzeige, odr?

Hautn das inzwischen mit deinem Binding hin? Bindest du eine IList<Person> an die BindingSource, oder nur ein einzelnen Person-Objekt (bei letzterem weißichnich, ob das geht).

Der frühe Apfel fängt den Wurm.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Es handelt sich erst einmal nur um eine TextBox welche ich an das Property "Name" binden möchte. Formatierung klappt, nur GUI kriegt nix davon mit, nach wie vor.

Welche Argumente sprechen genau dagegen, die Formatierung innerhalb der BusinessSchicht vorzunehmen? Ich spreche dabei vor allem von Dingen wie "Eigennamen vorne groß, Rest klein" oa.

Gruß

Matze

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo syn87,

es ist in der Tat eine Frage der Sichtweise.

Wenn du sagst, der Name einer Person muss mit einem Großbuchstaben beginnen, dann ist das eine Aufgabe der Business-Schicht, weil es ja die (Eigenschaften der) Daten selbst betrifft.

Wenn du aber sagst, dass der Name einer Person mit einem Großbuchstaben beginnend dargestellt werden soll, dann ist es eine Aufgabe des GUIs. Also alle Aufbereitungen, die die Darstellung betreffen, gehören ins GUI. Also Tausenderpunkte wären für mich klar ein Fall fürs GUI.

Letztlich hilft es immer, die Sache sehr abstrakt zu sehen und sich vorzustellen, dass man für dieselbe fachliche Application eine ganz andere Art von UI hätte, z.B. ein Sprachdialog-UI. Was dann an Aufbereitung nicht mehr oder anders oder zusätzlich erfolgen müsste, dass gehört in die UI-Schicht. Was selbst dann noch gleich ist, gehört in die Business-Schicht.

herbivore

5.299 Beiträge seit 2008
vor 14 Jahren

meine Frage war nicht, an welche Property du welches Control bindest, sondern was genau du der BindingSource als DataSource zuweist: Eine Auflistung oder ein "Individuum"?

Mir ist grad unklar, was bei dir "Formatierung" bedeutet. Für mich bedeutet das, etwa ein DateTime in 6 Ziffern anzuzeigen ("18.07.09"), oder aber "Sonntag, der 18. Juli 2009" anzuzeigen.
Betrifft nur die Anzeige, der DateTime ist derselbe.
Kannich im einen Form mal so machen, im anderen vlt anners.

So Vorgaben wie "EigenNamen groß" deuten mir aber auf eine prinzipielle Korrektur der Eingabe hin. Also, dass du willst, wenn der User "hans klein" eingibt, dass dann trotzdem "Hans Klein" der Wert der Property ist.
Das ist keine Formatierung in meinem Verständnis, und das könnte man schon im Business-Layer machen, weil das geht ja den Wert an sich an, nicht nur seine Darstellung.

(Hmm, herbivore war schneller, aber jetz habichs schon getippt. Und meine Frage ist ja auch noch offen)

Der frühe Apfel fängt den Wurm.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Hallo ihr beiden,

es handelt sich nur um ein Objekt, ein Person Objekt.

Du hast recht. In dem Sinne ist Formatierung etwas weit gefasst. Grundsätzlich soll es darum gehen, dass der Benutzer z.b. nicht auf Groß und Kleinschreibung achten brauch, und demzufolge einfach "hans wurst" eingibt, was dann die BusinessSchicht korrigiert/formatiert. Ein weiterer Punkt sind Telefonnummern. hier soll z.b. 0171 1234 56-98 in folgende überführt werden +49 (0) 171 1234 56 - 98.

In welche Schicht das jetzt genau gehoert ist ja fuer den Sachverhalt egal. Ich wuerde es jedenfalls gerne in die BusinessSchicht packn. Aber hat jetzt jemand eine Idee wie ich das Problem der Aktualisierung löse?

Um es nochmal auf den Punkt zu bringen.

  • ich binde ein Objekt
  • setze eine Eigenschaft per Code (Formatierung)
    -> die GUI aktualisiert nicht (Problem)

LG

5.299 Beiträge seit 2008
vor 14 Jahren

was sollich sagn - bei mir gehts.


   public partial class Form1 : Form {
      public Form1() {
         InitializeComponent();
         bindingSource1.DataSource = new Class1() { Txt = "Hallo" };
      }

      private void button1_Click(object sender, EventArgs e) {
         ((Class1)bindingSource1.DataSource).Txt = "huhu";
      }

   }

   class Class1 : INotifyPropertyChanged {
      #region INotifyPropertyChanged-Member
      public event PropertyChangedEventHandler PropertyChanged = delegate { };

      protected void OnPropertyChanged(string propName) {
         PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }

      protected bool SetProperty<TProp>(string propName, ref TProp backingField, TProp value) {
         if (object.Equals(backingField, value)) return false;
         backingField = value;
         PropertyChanged(this, new PropertyChangedEventArgs(propName));
         return true;
      }
      #endregion INotifyPropertyChanged-Member

      private string _txt;
      public String Txt { get { return _txt; } set { SetProperty("Txt", ref _txt, value); } }
   }

... und eine "textBox1" ist im Designer an den Datamember "Txt" der BindingSource gebunden (Knoten "DataBindings" erweitert)

Der frühe Apfel fängt den Wurm.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Hi,

also dein Beispiel geht bei mir auch. Wenn das allerdings beim verlassen einer TextBox passiert, also beim SetProperty dein value veraendert wird, dann kommts nicht zurueck.

LG

5.299 Beiträge seit 2008
vor 14 Jahren

das ist dann wohl eine Besonderheit, dass du den eingegebenen Wert korrigierst, in genau dem Moment, wo er eingegeben wird.
Und das Databinding aktualisiert das EingabeControl grade nicht, weiles denkt, "das hat die Eingabe ja grade gemacht, das soll wohl aktuell sein".
evtl. im textBox1_LostFocus-Event ein textBox1.Invalidate(), und wenn das nicht hilft, sogar ein bindingSource.ResetBindings()

Der frühe Apfel fängt den Wurm.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Hallo an alle 😃

Also ich hab es aufgegeben die Formatierung in das BusinessObject zu packen. Stattdessen sollte man Formatierungen über das [DataBinding].Parse Event auslösen.

Also z.b. textBox.DataBindings["Text"].Parse. Über den EventHandler kann man dann die Value anpassen/formatieren.

Gruß

5.299 Beiträge seit 2008
vor 14 Jahren

cool!

Damit hastedie AutoKorrektur ins Gui verlegt, was m.E. eine gute Idee ist. Es ist quasi eine AutoKorrektur-Textbox geschaffen, über die man die Daten nur im gewünschten Format eingeben kann.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;

namespace AutoCorrect {
   public partial class Form1 : Form {

      private Person _person = new Person();

      public Form1() {
         InitializeComponent();
         //im Designer festgelegte Bindings nachbessern
         firstNameTextBox.DataBindings["Text"].Parse += bnd_Parse;
         nameTextBox.DataBindings["Text"].Parse += bnd_Parse;
         personBindingSource.DataSource = _person;
      }

      void bnd_Parse(object sender, ConvertEventArgs e) {
         e.Value = e.Value.ToString().ToUpper();
      }

   }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace AutoCorrect {
   public class Person : INotifyPropertyChanged {

      #region INotifyPropertyChanged-Member
      public event PropertyChangedEventHandler PropertyChanged = delegate { };

      protected void OnPropertyChanged(string propName) {
         PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }

      protected bool SetProperty<TProp>(string propName, ref TProp backingField, TProp value) {
         if (object.Equals(backingField, value)) return false;
         backingField = value;
         PropertyChanged(this, new PropertyChangedEventArgs(propName));
         return true;
      }
      #endregion INotifyPropertyChanged-Member

      private string _name;
      public String Name {
         get { return _name; }
         set { SetProperty("Name", ref _name, value); }
      }

      private string _firstName;
      public String FirstName {
         get { return _firstName; }
         set { SetProperty("FirstName", ref _firstName, value); }
      }
   }
}

Der frühe Apfel fängt den Wurm.

S
syn87 Themenstarter:in
87 Beiträge seit 2008
vor 14 Jahren

Genau 😃

Danke für das Beispiel. Dann hat jeder nochmal ein Anhaltspunkt.