You are not logged in.
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.
Pages: 1
Topic closed
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
How about the CellDataChanged event.
Offline
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
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
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
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
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
Hello Jing,
Ok.. How would i do that..
You could just ignore reading properties from private objects.
Since i never had reason to that before?
Shane
Offline
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
Hello Jing,
Thank you. That worked.. Weird thing is that i knew how to do that.. was not just thinking..
Shane
Offline
Pages: 1
Topic closed