none
Warum werden gleiche Strings als ungleich erkannt? RRS feed

  • Frage

  • Hallo,

    ich habe Klassen deren Instanzen zum Editieren in einer Page angezeigt werden können. Ich möchte automatisch feststellen ob sich etwas geändert hat. Um das Objekt dann zu speichern.

    Dazu wollte ich im NavigateTo Ereignis die Property Werte sichern und diese beim Verlassen
    der Page mit den aktuellen Werten der Instanz vergleichen.
    (Über das Binding werden die Control Werte direkt in das Objekt übertragen.)
    Doch auch wenn ich nur mit Tab oder mit der Maus durch die Textboxen gehe wird oft
    bei gleichen String Werten eine Ungleichheit beim Stringvergleich vorher und nachher angezeigt.
    Wie kann das sein? Beim Debug erscheinen beide Strings gleich.

        [XmlIgnore]
        internal SortedList<string, string> Properties_Persist_Value_List_On_Page_Navigated_To =
                 new SortedList<string, string>();
        internal bool page_Control_Value_Changed;
    
    
        internal void Properties_Persist_Values_Save_On_Page_Navigated_To()
        {
          bool Property_Save_To_List;
    
          Properties_Persist_Value_List_On_Page_Navigated_To.Clear();
    
          PropertyInfo[] pi_List = this.GetType().GetProperties
                                   (BindingFlags.Instance 
                                   | BindingFlags.Public);
    
          foreach (PropertyInfo pi in pi_List)
          {
            Property_Save_To_List = Property_Save_To_List_Test(pi);
            if (Property_Save_To_List)
            {
              object pi_Property_Value = pi.GetValue(this);
    
              Properties_Persist_Value_List_On_Page_Navigated_To.Add
                (pi.Name, pi_Property_Value.ToString());
            }
          }                                         
        }
    
        internal void Properties_Persist_Value_List_Compare(ref bool page_Control_Value_Changed_p)
        {
          bool Property_Save_To_List;
    
          page_Control_Value_Changed_p = false;
    
          PropertyInfo[] pi_List = this.GetType().GetProperties
                                   (BindingFlags.Instance
                                   | BindingFlags.Public);
    
          foreach (PropertyInfo pi in pi_List)
          {
            Property_Save_To_List = Property_Save_To_List_Test(pi);
            if (Property_Save_To_List)
            {
              string pi_Property_Value = pi.GetValue(this).ToString();
              
              if (pi_Property_Value !=
                  Properties_Persist_Value_List_On_Page_Navigated_To[pi.Name])
              {
                page_Control_Value_Changed_p = true;
                break;
              }
            }
          }
        }
    
    
        public bool Property_Save_To_List_Test(PropertyInfo pi_p)
        {
          bool Property_Save_To_List = true;
    
          if (pi_p.CanWrite == false)
            { Property_Save_To_List = false; }
          else
            {
              foreach (CustomAttributeData cAD in pi_p.CustomAttributes)
              {
                if (cAD.AttributeType.FullName ==
                    typeof(System.Xml.Serialization.XmlIgnoreAttribute).FullName)
                { Property_Save_To_List = false; }
              }
            }
    
          return Property_Save_To_List;
        }
    
    
    

    Sonntag, 9. Juni 2019 03:45

Antworten

  • Hallo Dimitar,

    Entschuldigung das ich so spät antworte. Ich habe den Vorschlag zwar als Antwort markiert um den Thread abzuschließen aber trotzdem meinen Ansatz gelassen. Dieser funktioniert auch. Ich kenne mich mit den XML Dingen nicht so aus als das ich noch herum probieren wollte.

    Der Vorschlag dort war:

    XmlWriterSettings wss = new XmlWriterSettings();
    ws.NewLineHandling = NewLineHandling.Entitize;
    
    XmlSerializer seria = new XmlSerializer( typeof( Test) );
    using (XmlWriter wr = XmlWriter.Create( "test.xml", wss)) {
        seria.Serialize( wr, s );
    }

    Mein eigener Code
                    var serializer = new XmlSerializer(typeof(T));
    
                    Windows.Storage.StorageFile file = await file_Folder.CreateFileAsync
                            (filename, Windows.Storage.CreationCollisionOption.ReplaceExisting);
    
                    Stream stream = await file.OpenStreamForWriteAsync();
                    using (stream)
                    {
                        serializer.Serialize(stream, objectToSave);
                    }
       

    Mittwoch, 10. Juli 2019 18:57

Alle Antworten

  • Der Vergleich, also die Prozedur Properties_Persist_Value_List_Compare wird im Back_Button_Click Eventhandler nach dem Frame.GoBack() Aufruf aufgerufen.

    Wenn ich ohne den Cursor zu bewegen gleich nach Aufruf der Page den Back Button klicke werden alle Strings als gleich erkannt. Gehe ich jedoch mit Tab oder mit der Maus durch Text-Boxen, bekommen diese also Focus werden gleiche Strings dann als ungleich erkannt.

    private async void Back_Button_Click(object sender, RoutedEventArgs e)
        {
          if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack();
    
          ViewModel.Properties_Persist_Value_List_Compare(ref ViewModel.page_Control_Value_Changed);
    
    ...


    Sonntag, 9. Juni 2019 04:52
  • Das seltsame ist diese Ungleichheit wird einmal festgestellt.
    Wenn das Objekt frisch mit XML deserialisiert ist und zum ersten Mal in der
    Page angezeigt wird.

    Beim Wiederholten anzeigen und durchgehen mit der Maus ist es dann gleich.
    Wenn ich den Vergleich Zeichen für Zeichen mache sehe ich das es beim Zeilenumbruch
    bei einem mehrzeiligen Textfeld geschieht.

    Frisch deserialisiert ist das \n
    nach wiederholtem Aufruf der Page und durchgehen der Felder mit der Maus \r

    XML Serialisierung und XAML scheinen unterschiedliche Zeichen für den Zeilenumbruch in einem
    String zu verwenden? Wie kann ich da am besten vorgehen?


              if (pi_Property_Value !=
                  Properties_Persist_Value_List_On_Page_Navigated_To[pi.Name])
              {
                page_Control_Value_Changed_p = true;
              }
    
              page_Control_Value_Changed_p = false;
              if (! MyStringCompare(pi_Property_Value, 
                                    Properties_Persist_Value_List_On_Page_Navigated_To[pi.Name])) 
              {
                page_Control_Value_Changed_p = true;
                break;
              }
    
    ..
    
    bool MyStringCompare(string str1, string str2)
        {
          if (str1 == null && str2 == null)
          { return true;  }
    
          if (str1 == null || str2 == null)
          { return false; }
    
          if (str1.Length != str2.Length)
          { return false; }
    
          for (int i = 0; i < str1.Length; i++)
          {
            if (str1.Substring(i,1) != str2.Substring(i,1))
            { return false; }
          }
    
          return true;
        }




    • Bearbeitet Markus222 Sonntag, 9. Juni 2019 17:43
    Sonntag, 9. Juni 2019 07:28
  • Habe das XML "\n" mit dem XAML "\r" direkt nach der Deserialisierung ersetzt.
    In I_Entry_Dictorary_ValueArray sind die deserialisierten Objekte einer Klasse.
    Gibt es eine Möglichkeit XML mitzuteilen welchen Escape Character es da verwenden soll?
    Ich denke das kann eine Fehlerursache beim Vergleichen von Strings sein wenn
    die Steuerzeichen für den Zeilenvorschub unterschiedlich sind.

     


          i_Entry_Dictionary_p.Clear();
              foreach (I_Entry_Dictionary_ValueType
                       i_Entry_Dictionary_Value_Array_Member
                       in i_Entry_Dictionary_Value_Array)
              {
                ///////////////////////////////////////////////////////////
                ///
    
                PropertyInfo[] pi_List = i_Entry_Dictionary_Value_Array_Member.GetType().
                                         GetProperties();
    
                foreach (PropertyInfo pi in pi_List)
                {
    
                  object pi_Property_Value = pi.GetValue(i_Entry_Dictionary_Value_Array_Member);
                  if (pi_Property_Value is String str_Property_Value)
                  {
                    if (str_Property_Value.Contains("\n"))
                    {
                      str_Property_Value = str_Property_Value.Replace("\n", "\r");
                      pi.SetValue(i_Entry_Dictionary_Value_Array_Member, str_Property_Value);
                    }
                  }
                }
    
                FieldInfo[] fi_List = i_Entry_Dictionary_Value_Array_Member.GetType().
                                      GetFields();
    
                foreach (FieldInfo fi in fi_List)
                {
    
                  object fi_Field_Value = fi.GetValue(i_Entry_Dictionary_Value_Array_Member);
                  if (fi_Field_Value is String str_Field_Value)
                  {
                    if (str_Field_Value.Contains("\n"))
                    {
                      str_Field_Value = str_Field_Value.Replace("\n", "\r");
                      fi.SetValue(i_Entry_Dictionary_Value_Array_Member, str_Field_Value);
                    }
                  }
                }
    
                //////////////////////////////////////////////////////////////
    
    
                i_Entry_Dictionary_p.Add
                        (i_Entry_Dictionary_Value_Array_Member.Dictionary_Key,
                         i_Entry_Dictionary_Value_Array_Member);
              }
            }
            else
            {
              // Offen: File nicht vorhanden.
            }
          }
     

    Montag, 10. Juni 2019 10:32
  • Hallo Markus,

    Ich verlinke hier der Übersichtlichkeit halber Deinen Thread aus dem englischsprachigen Forum, der eine Lösung enthält. Würdest Du hier auch auf Deutsch das Verfahren mit der XmlWriterSettings-Klasse zusammenfassen und als Antwort markieren, sodass sie auch künftigen Lesern dieses Threads zur Verfügung steht?

    Gruß,
    Dimitar

    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Mittwoch, 26. Juni 2019 12:45
    Moderator
  • Hallo Dimitar,

    Entschuldigung das ich so spät antworte. Ich habe den Vorschlag zwar als Antwort markiert um den Thread abzuschließen aber trotzdem meinen Ansatz gelassen. Dieser funktioniert auch. Ich kenne mich mit den XML Dingen nicht so aus als das ich noch herum probieren wollte.

    Der Vorschlag dort war:

    XmlWriterSettings wss = new XmlWriterSettings();
    ws.NewLineHandling = NewLineHandling.Entitize;
    
    XmlSerializer seria = new XmlSerializer( typeof( Test) );
    using (XmlWriter wr = XmlWriter.Create( "test.xml", wss)) {
        seria.Serialize( wr, s );
    }

    Mein eigener Code
                    var serializer = new XmlSerializer(typeof(T));
    
                    Windows.Storage.StorageFile file = await file_Folder.CreateFileAsync
                            (filename, Windows.Storage.CreationCollisionOption.ReplaceExisting);
    
                    Stream stream = await file.OpenStreamForWriteAsync();
                    using (stream)
                    {
                        serializer.Serialize(stream, objectToSave);
                    }
       

    Mittwoch, 10. Juli 2019 18:57