Click here to Skip to main content
15,949,741 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello.

I am wondering is there a possible way to track when some string has changed. Not only by length but in stored data.
Example:
C#
string asd = "test data";

asd = "test_data";


Here we have a change. I am wondering how to track it, give me some examples.
Posted

.NET has provided two Interfaces used in specifying the monitoring of changes to Properties since version 2.0: INotifyPropertyChanging, and INofifyPropertyChanged.

Beginning in .NET 4.5 a new feature was added for avoiding having to hard code the name of the property changing/changed into the call:

.NET 2.0 to .NET 3.5:

C#
using System.ComponentModel;

namespace YourNameSpace
{
    public class PropertyNotificationDemo : INotifyPropertyChanging, INotifyPropertyChanged
    {
        public event PropertyChangingEventHandler PropertyChanging;
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanging(string data)
        {
            if (PropertyChanging != null) PropertyChanging(this, new PropertyChangingEventArgs(data));
        }

        private void NotifyPropertyChanged(string data)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(data));
        }

        // property that implements PropertyChanging
        private string someString;
    
        public string SomeString
        {
            get { return someString; }
    
            set
            {
                if (value != someString)
                {
                    NotifyPropertyChanging("SomeString");
                    someString = value;
                }
            }
        }

        // property that implements PropertyChanged
        private string anotherString;

        public string AnotherString
        {
            get { return anotherString; }
    
            set
            {
                if (value != anotherString)
                {
                    anotherString = value;
                    NotifyPropertyChanged("AnotherString");
                }
            }
        }
    }
}


You use these Event declarations that implement the Property Changing/Changed facilities by creating instances of the Class and subscribing to the Events like you would any other custom Event:

C#
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace YourNameSpace
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // declare in Form Class scope
        PropertyNotificationDemo pnd = new PropertyNotificationDemo();
    
        private void Form1_Load(object sender, EventArgs e)
        {
            // initialize somewhere like in the Form Load EventHandler
            pnd.PropertyChanging += pnd_PropertyChanging;
            pnd.PropertyChanged += pnd_PropertyChanged;
            pnd.SomeString = "hello";
            pnd.AnotherString = "goodbye";
        }
    
        // define the EventHandlers
        private void pnd_PropertyChanging(object sender, PropertyChangingEventArgs e)
        {
            MessageBox.Show(string.Format("{0} is changing", e.PropertyName));
        }

        private void pnd_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            MessageBox.Show(string.Format("{0} is changed", e.PropertyName));
        }
    }
}


Beginning with .NET 4.5: the 'CallerMemberName Attribute was added: now the Class that uses the new Property Changed/Changing requires:

C#
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace YourNameSpace
{
    public class PropertyNotificationDemo : INotifyPropertyChanging, INotifyPropertyChanged
    {
        public event PropertyChangingEventHandler PropertyChanging;
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanging([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanging != null) PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        // property that implements PropertyChanging
        private string someString;
    
        public string SomeString
        {
            get { return someString; }
    
            set
            {
                if (value != someString)
                {
                    NotifyPropertyChanging();
                    someString = value;
                }
            }
        }

        // property that implements PropertyChanged
        private string anotherString;
    
        public string AnotherString
        {
            get { return anotherString; }
    
            set
            {
                if (value != anotherString)
                {
                    anotherString = value;
                    NotifyPropertyChanged();
                }
            }
        }
    }
}


And, the EventHandlers in the Form that creates an instance of, and uses, this Class look like this:

C#
private void pnd_PropertyChanging(object sender, PropertyChangingEventArgs e)
{
    MessageBox.Show(string.Format("{0} is changing", e.PropertyName));
}

private void pnd_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    MessageBox.Show(string.Format("{0} is changed", e.PropertyName));
}
 
Share this answer
 
v5
Comments
Agent__007 7-Apr-15 0:36am    
Thanks, didn't know about "CallerMemberName". :thumbsup:
Yes, this is possible, for each particular string member. You just need to make it a property (but Solution 1 is by far not sufficient). Here is how:
C#
public class StringChangeEventArgs : System.EventArgs {
    public StringChangeEventArgs(string before, string after) {
        this.Before = before;
        this.After = after;
    }
    internal string Before { get; private set; }
    internal string After { get; private set; }
}

public class StringChangeDetectableOne {
    public string Trackable {
        get { return trackableBackingString; }
        set { 
            if (value == trackableBackingString)
                return;
            string old = trackableBackingString;
            trackableBackingString = value;
            if (StringModified != null)
                StringModified.Invoke(old, value);
        }
    }
    string trackableBackingString;
    public event System.EventHandler<StringChangeEventArgs> StringModified;
}

Usage, one of the possible ways:
C#
class Test {
    void Test() {
        StringChangeDetectableOne testObject = new StringChangeDetectableOne();
        testObject.StringModified += (sender, eventArgs) => {
            string oldValue = eventArgs.Before;
            string newValue = eventArgs.After;
            // do something with the notification
            // using oldValue and newValue
        };
    }
}


This way, some method added to the notification list of the event instance declared above will get the notification on each modification of the string, only if new value is different from old one.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900