ReoGrid Forum

Fast and powerful .NET Spreadsheet Component

You are not logged in.

Announcement

This forum has been archived and no longer accepts new user registrations. Please report your questions, problems, and feedback to the issue page of ReoGrid on GitHub. Thank you for your cooperation.

https://github.com/unvell/ReoGrid/issues

#1 2015-03-26 23:27:25

asparatu
Member
Registered: 2014-08-20
Posts: 196

Tracking worksheet Control for changes

Hello Jing,
   I want to know if can track individual changes in the control at the object level. What i mean is if have list of worksheets i want to be able to check if something has changed and update the control in that list so i can tell if there has been changes so i can save the data. example; I have textbox and want to check the text input so i have original value and new value to tell me it should save data or not. the reason why i ask. I need to track changes in form so i can save to dataset then save that to file.

I think with yours i would have to track the collection of cells? or the sheet.data object.

here is sample of what the code will do

public class ControlDirtyTracker
    {
        private Control _control;
        private string _cleanValue;

        // read only properties
        public Control Control { get { return _control; } }
        public string CleanValue { get { return _cleanValue; } }              

        // constructor establishes the control and uses its current value as "clean"
        public ControlDirtyTracker(Control ctl)
        {            
            // if the control type is not one that is supported, throw an exception
            if (ControlDirtyTracker.IsControlTypeSupported(ctl))
                _control = ctl;            
            else
                throw new NotSupportedException(
                    string.Format("The control type for '{0}' is not supported by the ControlDirtyTracker class."
                      , ctl.Name)
                    );
                    
        }


        // method to establish the the current control value as "clean"
        public void EstablishValueAsClean()
        {
            _cleanValue = GetControlCurrentValue();
        }


        // determine if the current control value is considered "dirty"; 
        // i.e. if the current control value is different than the one
        // remembered as "clean"
        public bool DetermineIfDirty()
        {
            // compare the remembered "clean value" to the current value;
            // if they are the same, the control is still clean;
            // if they are different, the control is considered dirty.
            return (string.Compare(_cleanValue, GetControlCurrentValue(), false) != 0);
        }



        //////////////////////////////////////////////////////////////////////////////////////
        // developers may modify the following two methods to extend support for other types
        //////////////////////////////////////////////////////////////////////////////////////
        
        // static class utility method; return whether or not the control type 
        // of the given control is supported by this class;
        // developers may modify this to extend support for other types
        public static bool IsControlTypeSupported(Control ctl)
        {
            // list of types supported
            if (ctl is TextBox) return true;
            if (ctl is CheckBox) return true;
            if (ctl is ComboBox) return true;
            if (ctl is ListBox) return true;

            // ... add additional types as desired ...                       

            // not a supported type
            return false;
        }
        

        // private method to determine the current value (as a string) of the control;
        // if the control is not supported, return a NotSupported exception
        // developers may modify this to extend support for other types
        private string GetControlCurrentValue()
        {
            if (_control is TextBox)
                return (_control as TextBox).Text;

            if (_control is CheckBox)
                return (_control as CheckBox).Checked.ToString();

            if (_control is ComboBox)
                return (_control as ComboBox).Text;

            if (_control is ListBox)
            {
                // for a listbox, create a list of the selected indexes
                StringBuilder val = new StringBuilder();
                ListBox lb = (_control as ListBox);
                ListBox.SelectedIndexCollection coll = lb.SelectedIndices;
                for (int i = 0; i < coll.Count; i++)
                    val.AppendFormat("{0};", coll[i]);
                
                return val.ToString();                
            }

            // ... add additional types as desired ...

            return "";
        }

    }
public class ControlDirtyTrackerCollection: List<ControlDirtyTracker>
    {

        // constructors
        public ControlDirtyTrackerCollection() : base() { }
        public ControlDirtyTrackerCollection(Form frm) : base() 
        { 
            // initialize to the controls on the passed in form
            AddControlsFromForm(frm); 
        }


        // utility method to add the controls from a Form to this collection
        public void AddControlsFromForm(Form frm)
        {
            AddControlsFromCollection(frm.Controls);
        }

        // recursive routine to inspect each control and add to the collection accordingly
        public void AddControlsFromCollection(Control.ControlCollection coll)
        {
            foreach (Control c in coll)
            {
                // if the control is supported for dirty tracking, add it
                if (ControlDirtyTracker.IsControlTypeSupported(c))
                    this.Add(new ControlDirtyTracker(c));

                // recurively apply to inner collections
                if (c.HasChildren)
                    AddControlsFromCollection(c.Controls);
            }
        }

        // loop through all controls and return a list of those that are dirty
        public List<Control> GetListOfDirtyControls()
        {
            List<Control> list = new List<Control>();

            foreach (ControlDirtyTracker c in this)
            {
                if (c.DetermineIfDirty())
                    list.Add(c.Control);
            }

            return list;
        }


        // mark all the tracked controls as clean
        public void MarkAllControlsAsClean()
        {
            foreach (ControlDirtyTracker c in this)
                c.EstablishValueAsClean();
        }

    }

Shane

Offline

#2 2015-03-26 23:58:16

Jingwood
Moderator
From: jing at reogrid.net
Registered: 2014-06-03
Posts: 615

Re: Tracking worksheet Control for changes

How about the CellDataChanged event.

Offline

#3 2015-03-27 15:28:34

asparatu
Member
Registered: 2014-08-20
Posts: 196

Re: Tracking worksheet Control for changes

Hello Jing,
  I could use that but i need to check if there is change in the between the two sets of data and if so it will mark the form as dirty..and it will save so i can save the data.

Shane

Offline

#4 2015-03-27 16:01:12

Jingwood
Moderator
From: jing at reogrid.net
Registered: 2014-06-03
Posts: 615

Re: Tracking worksheet Control for changes

How many objects you need to check?

Okay. I'm afraid there is no perfect solution to compare exactly the difference from two worksheets, you might need to compare all cells from two worksheets one by one. You could backup a cloned worksheet at form-load (Worksheet.Copy method), then compare it to last status of worksheet at form-close. If you have a large worksheet, this might spend huge memory and a lot of time.

Usually in my own application I will use some compromise methods rather than check a data-set, especially when there is many objects need to be compared. I will consider to use the CellDataChanged event, if this event raised once, the form will be marked as dirty. Some application also use the way like this, you might found that applications prompted you 'Document has changed', but actually you've revoked all actions and document has been restore, there is nothing changed. I want to say, if you don't need very high accuracy, the CellDataChanged, RangeStyleChanged, BorderAdded and BorderRemoved are just fine.

If it is necessary to compare two worksheets, compare only the row count and column count firstly, then compare the data content. I think that might help to improvement the process speed.

Offline

#5 2015-03-27 16:44:30

asparatu
Member
Registered: 2014-08-20
Posts: 196

Re: Tracking worksheet Control for changes

Hello Jing,
   The first form i am trying this on only has 9 controls including the worksheet.. and most of the worksheet only have 30 row and 4 columns. there is on that will 512 row and up to 5 columns.. I will think about what you are talking about..

Shane

Offline

#6 2015-04-11 18:04:52

asparatu
Member
Registered: 2014-08-20
Posts: 196

Re: Tracking worksheet Control for changes

Hello Jing,
    I am able to track changes in on my form with the code in my first post. The way it works that takes the values and make them into a string and compare the string values. i have added your control to the list of valid controls but one weird thing happens. I fine my defined control and then finds another control called unvell.ReoGrid.ReoGridControl.a when you look at the control name the text says, "Unable to evaluated expression." I only have one reogrid control on the form.. any idea why this would be there?

I see what is happening.. When i check for the controls on the form it is somehow show to reogrid controls on the form when there is just one. any reason why this would be happening?

Shane

Last edited by asparatu (2015-04-11 18:46:43)

Offline

#7 2015-04-13 06:07:18

Jingwood
Moderator
From: jing at reogrid.net
Registered: 2014-06-03
Posts: 615

Re: Tracking worksheet Control for changes

ReoGrid (Windows Forms version) contains a few of small controls inside to handle user editing, screen scroll and sheet switching, these controls might called like A, B or something else. They were defined as private objects and not available to user code, seems your program has found these controls and attempt to read data from them. You could just ignore reading properties from private objects.

Offline

#8 2015-04-13 15:56:37

asparatu
Member
Registered: 2014-08-20
Posts: 196

Re: Tracking worksheet Control for changes

Hello Jing,
  Ok.. How would i do that..

Jing wrote:

You could just ignore reading properties from private objects.

Since i never had reason to that before?
Shane

Offline

#9 2015-04-14 04:10:22

Jingwood
Moderator
From: jing at reogrid.net
Registered: 2014-06-03
Posts: 615

Re: Tracking worksheet Control for changes

You should change the code:

                // recurively apply to inner collections
                if (c.HasChildren)
                    AddControlsFromCollection(c.Controls);

to

                // recurively apply to inner collections
                if (c.HasChildren && !(c is ReoGridControl))
                    AddControlsFromCollection(c.Controls);

Your code seems to scan all controls from a window recursively, but you need to ignore scan children from ReoGridControl.

Last edited by Jingwood (2015-04-14 04:10:32)

Offline

#10 2015-04-14 23:55:47

asparatu
Member
Registered: 2014-08-20
Posts: 196

Re: Tracking worksheet Control for changes

Hello Jing,
   Thank you. That worked.. Weird thing is that i knew how to do that.. was not just thinking..
Shane

Offline

Board footer

Powered by FluxBB