none
The strings are equal. Why says string comparison they are not equal? RRS feed

  • Question

  • Hello,

    i have instances of classes to edit in a page. I want to see if they are changed. If so i want to save the object.

    Therefore i wanted to save the values of the properties in the OnNavigatedTo event. When i leave the page i want to compare the current Values with the saved Values. (The Bindings transport the values of the controls directly to the object.)

    But even when i go with the Tab Key or with the mouse through the TextBoxes and don't change anything the same strings are recognized as not equal.

    How can this be? In Debug the strings are equal but comparison says not equal.

    [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;
        }
    
    


    Sunday, June 9, 2019 4:04 AM

Answers

  • @Markus222,

    OK. I think there might be a workaround for you. Try to use the following pattern to write the code:

    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 );
    }

    In this way, you are telling the Serializer to recognize the new line. 

    Best regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by Markus222 Friday, June 14, 2019 12:50 PM
    Wednesday, June 12, 2019 9:53 AM
    Moderator

All replies

  • The string comparison, the procedure Properties_Persist_Value_List_Compare, is called in the Back_Button_Click Eventhandler after the Frame.GoBack() Call.

    Wenn i cklick the Back Button immediately after the page is shown without doing anything else all strings are recogized as equal. When i go with the mouse in a text box or with the Tab-Key throug text boxes, when they get focus (without changing the text) the equal strings are recognized as not equal. Why?

    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);
    
    ...
    


    Sunday, June 9, 2019 4:59 AM
  • The not equal is recognized only when the object is freshly deserialized from xml
    and shown the first time in the page.
    If i edit and show the object again the fields are recogized as equal even when
    i go through them with the mouse.

    If i make the string comparison character by character i see that the wordwrap in the
    strings in a multiline TextBox is different.

    Fresh deserialized it is \n
    and after i go in the TextBox with the mouse ist is \r

    XML Serialization and XAML seem to use different characters for wordwrap? How can i fix this?


           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;
        }





    • Edited by Markus222 Sunday, June 9, 2019 5:43 PM
    Sunday, June 9, 2019 7:34 AM
  • @Markus,

    Can you provide a simple repro to us? You've shared the way how you compare your value but the keypoint here is about:

    "Fresh deserialized it is \n
    and after i go in the TextBox with the mouse ist is \r"

    To fix your issue I think we may need to modify based on your code on this deserialize behavior.

    Best regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, June 10, 2019 7:35 AM
    Moderator
  • I did replace the XML "\n" with the XAML "\r" directly after Deserialization.
    In I_Entry_Dictionary_ValueArray are the deserialized Objects.

    Is there a way to tell XML which Escape Character to use?
    I think this different behavior for linefeeds can cause errors when compare the strings.

             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.
            }
          }
     

    Monday, June 10, 2019 10:27 AM
  • How did you write the code to get i_Entry_Dictionary_Value_Array? Maybe we can convert it while using the xml writter.

    Regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, June 11, 2019 6:19 AM
    Moderator
  • I can not send the whole project. There are many classes. And therefore i use generics.

    // The procedures to Serialize:
    
    
        internal async Task Entry_List_File_Serialize_Call(string P_Caller_N)
        {
          await Entry_ViewModel.
                I_Entry_Dictionary_Serialize
                <SortedList<string, Entry>, T_Entry_Class>
                (entry_List,
                 AppGlobals.AppGlobals.App_Folder,
                 Entry_List_File_Name,
                 P_Caller_N);
        }
    
    
        internal static async Task I_Entry_Dictionary_Serialize
                              <I_Entry_Dictionary_Type,
                               I_Entry_Dictionary_ValueType>
                              (I_Entry_Dictionary_Type i_Entry_Dictionary_p,
                               StorageFolder sourceFolder_p,
                               string file_Name_p,
                               string P_Caller_N)
                               where I_Entry_Dictionary_Type : System.Collections.IDictionary
                               where I_Entry_Dictionary_ValueType : I_Entry_Dictionary
          // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        {
          string NCN_pn = NCN + "." + nameof(I_Entry_Dictionary_Serialize);
          Exception p_ex = null;
    
          try
          {
            // Offen Caller. Auch bei Deserialize.
    
            int i = -1;
    
            I_Entry_Dictionary_ValueType[]
            i_Entry_Dictionary_Value_Array =
            new I_Entry_Dictionary_ValueType
                [i_Entry_Dictionary_p.Count];
    
            foreach (I_Entry_Dictionary_ValueType
                     i_Entry_Dictionary_Value
                     in i_Entry_Dictionary_p.Values)
            {
              i = i + 1;
              i_Entry_Dictionary_Value_Array[i]
              = i_Entry_Dictionary_Value;
            }
    
            // Offen: Die Methode von Adam Nathan probieren.
            await AppGlobals.Types.Serialization.Xml_Serialization.
              Xml_Serialization.
              ObjectSaveToXmlFile
              (i_Entry_Dictionary_Value_Array,
               sourceFolder_p,
               file_Name_p);
          }
          catch (Exception ex) { p_ex = ex; }
    
          if (p_ex != null)
          {
            // Offen: Meldung.
            Exception_Handle.Exception_ReThrow1
            (NCN_pn,
             "",
             p_ex);
          }
        }
    
            public static async Task ObjectSaveToXmlFile<T>
                                     (T objectToSave,
                                      StorageFolder file_Folder,
                                      string filename)
            {
                Exception p_ex = null;
    
                try
                {
    
                    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);
                    }
                }
                catch (Exception ex) { p_ex = ex; }
    
                if (p_ex != null)
                {
                    // Offen: 
                    // Meldung und ReThrow.
                    await Exception_Handle.Exception_MessageDialog_Show1
                    ("", 
                     "",
                     p_ex);
                }
            }
    
    
    
    // The procedures to Deserialize:
    
        internal async Task Entry_List_File_Deserialize_Call(string P_Caller_N)
        {
          await Entry_ViewModel.
                 I_Entry_Dictionary_Deserialize
                 <SortedList<string, Entry>, T_Entry_Class>
                 (entry_List,
                  AppGlobals.AppGlobals.App_Folder,
                  Entry_List_File_Name,
                  P_Caller_N);
        }
    
    
        // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        internal static async Task I_Entry_Dictionary_Deserialize
                              <I_Entry_Dictionary_Type,
                               I_Entry_Dictionary_ValueType>
                              (I_Entry_Dictionary_Type i_Entry_Dictionary_p,
                               StorageFolder sourceFolder_p,
                               string file_Name_p,
                               string P_Caller_N)
                               where I_Entry_Dictionary_Type : System.Collections.IDictionary
                               where I_Entry_Dictionary_ValueType : I_Entry_Dictionary
          // ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        {
          // Offen: Eventuell der Asynchrone Ansatz von Adam Nathan.
    
          string NCN_pn = NCN + "." + nameof(I_Entry_Dictionary_Deserialize);
          Exception p_ex = null;
    
          StorageFile storagefile;
          PropertyInfo[] pi_List = null;
          FieldInfo[] fi_List = null;
    
          try
          {
            Debug.Assert
            (P_Caller_N == Entry_ViewModel_Initialize_pn,
             NCN_pn + " called from wrong procedure: " + P_Caller_N);
    
            storagefile
            = (Windows.Storage.StorageFile)
               await sourceFolder_p.TryGetItemAsync(file_Name_p);
    
            if (storagefile != null)
            {
              // Offen: Die Methode von Adam Nathan probieren.
              I_Entry_Dictionary_ValueType[] i_Entry_Dictionary_Value_Array =
              await AppGlobals.Types.Serialization.Xml_Serialization.
                    Xml_Serialization.
                    ObjectReadFromXmlFile<I_Entry_Dictionary_ValueType[]>
                    (storagefile);
    
              i_Entry_Dictionary_p.Clear();
              foreach (I_Entry_Dictionary_ValueType
                       i_Entry_Dictionary_Value_Array_Member
                       in i_Entry_Dictionary_Value_Array)
              {
    
    
                ///////////////////////////////////////////////////////////
                ///
                if (pi_List == null)
                {
                  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);
                    }
                  }
                }
    
                if (fi_List == null)
                {
                  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.
            }
          }
          catch (Exception ex) { p_ex = ex; }
    
          if (p_ex != null)
          {
            // Offen: Meldung.
            Exception_Handle.Exception_ReThrow1
            (NCN_pn,
             "",
             p_ex);
          }
        }
    
            public static async Task<T> ObjectReadFromXmlFile<T>
                                        (StorageFile storagefile)
            {
                T objectFromXmlFile = default(T);
    
                var serializer = new XmlSerializer(typeof(T));
    
                Stream stream = await storagefile.OpenStreamForReadAsync();
                objectFromXmlFile = (T)serializer.Deserialize(stream);
                stream.Dispose();
    
                return objectFromXmlFile;
            }
    
    
    

    Tuesday, June 11, 2019 2:13 PM
  • @Markus222,

    OK. I think there might be a workaround for you. Try to use the following pattern to write the code:

    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 );
    }

    In this way, you are telling the Serializer to recognize the new line. 

    Best regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by Markus222 Friday, June 14, 2019 12:50 PM
    Wednesday, June 12, 2019 9:53 AM
    Moderator