Cause xamDataGrid to repaint - c#

I need a way for viewmodel to instruct XamDataGrid on the view to just reread and repaint its cells with minimal hassle. I do not wish to mess with the source and do some unsustainable workaround with raising its events (the source might change).
To make it more understandable, I have a global static class that holds some visual cues configuration that do not affect data but only they way its represented in the grid (scaling, formatting, etc). The visual action happens in the IValueConverter implementation attached to the field which works just fine. There is a static event which fires when cues change and viewmodels subscribe to it and events fire properly. Now I just need to have the event handler cause the grid to repaint.
Any suggestions?
EDIT: some code, if it helps:
converter:
public class ScaleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType == typeof(double) || targetType == typeof(double?))
{
if (value == null && targetType == typeof(double?)) return null; // short circuit for null->null, nothing to scale
if (value is double) return (double)value / DisplayScale.Scale; // shortcut for direct scaling, no need to waste time on conversion
try
{
return System.Convert.ToDouble(value) / DisplayScale.Scale; // for convertible values, eat conversion exception
}
catch (Exception) {};
// if all esle fails return NaN
return double.NaN;
}
// fallthrough, return null, this should not happen, if it does it means converter is incomplete
return null;
}
...
}
DisplayScale global
public class DisplayScale: NotificationObject
{
private static KeyValuePair<string, double> _ActiveScaling;
private static readonly object _lockHandle = new object(); // note: should not contest, but just to be on the safe side
public static event Action ScalingChanged;
public static List<KeyValuePair<string, double>> ScaleList { get; private set; }
static DisplayScale()
{
ScaleList = new List<KeyValuePair<string, double>>()
{
new KeyValuePair<string, double>("No scaling (1's)", 1d),
new KeyValuePair<string, double>("Thousands (1,000's)", 1000d),
new KeyValuePair<string, double>("Millions (1,000,000's)", 1000000d),
new KeyValuePair<string, double>("Billions (1,000,000,000's)", 1000000000d)
};
ActiveScaling = ScaleList.First(); // OPTION: could be in per-user config
}
public static double Scale { get { return ActiveScaling.Value; } }
public static KeyValuePair<string, double> ActiveScaling
{
get
{
lock (_lockHandle) return _ActiveScaling;
}
set
{
lock (_lockHandle)
{
_ActiveScaling = value;
var eventCall = ScalingChanged;
if (eventCall != null) eventCall();
}
}
}
}
fields are defined as
// resource
<inf:ScaleConverter x:Key="ScaleConverter" />
// field
<igDP:Field Name="Deposit" Converter="{StaticResource ScaleConverter}">

if you have a collectionview than call simply Refresh() to it.
public class YourViewModel
{
private ObservableCollection<YourDataClass> yourColl;
public void YourViewModel()
{
yourColl = new ObservableCollection<YourDataClass>();
YourCollectionView = CollectionViewSource.GetDefaultView(yourColl);
DisplayScale.ScalingChanged += () => YourCollectionView.Refresh();
}
var ICollectionView yourCollView;
public ICollectionView YourCollectionView
{
get { yourCollView; }
set {
yourCollView = value;
RaisePropertyChanged("YourCollectionView");
}
}
}

I was having the same issue, and it turns out even though I had my ViewModel implement INotifyPropertyChanged, I was not implementing INotifyPropertyChanged on the class that the grid rows were binding to in my ObservableCollection (i.e. the YourDataClass in punker76's answer). Once I implemented it on that class as well everything started updating as expected.
I know that you mentioned "I do not wish to mess with the source" so I'm not sure if this solution is acceptable for you, but I thought I would share for others that find this post as well.

Related

Property edit style as DropDown in a VS .NET custom component

I'd like to use the functionality of a ComboBox as edit option for a var in the properties window of a custom control / component. Not the ComboBox component itself.
As example:
private string[] _stringArray = { "string0", "string1" };
public string[] StringArray
{
get { return _stringArray; }
//callback
//set { _stringArray = value; }
}
As you know this will give me the object browser as view/edit option in the property window.
Funny thing that I can edit the values even with no setter.
In my researches I found out that it is possible ("UITypeEditorEditStyle.DropDown"). But I have no idea how to implement that.
Or what [Instructions] I could set for the "StringArray".
My final goal is a copy of the object selector drop-down of visual studio as a property parameter:
With custom event handling of course. But as you see I'm far away to realize that. :(
I have been looking for a tutorial on the following topics for a long time:
[Designer] instructions reference
A basic tutorial how to manage the display style of properties ✔
However I'm tired of my unsuccessful researches. Some good links are always welcome.
UPDATE:
After I more or less understood the principle (from the link in the comments, thanks) I came to an interim solution.
I realized that I need at least an int var to set a selected `index`. I thought / hoped that VS can do this automatically. Like it does with enums. And my lack of knowledge concerning [Instructions].
I could define a string variable as a placeholder for the selected index of the array in order to do without the TypeConverter, but that would make even less sense. I really don't need another abstract variable for nothing.
So the basis drop-down, which e.g. can display enums directly, does not appear to be applicable. So they use a trick with "UITypeEditorEditStyle.DropDown", which actually isn't a drop-down. It's just a button where you can place the control of your choice. In my case a ListView. Since the "drop" of the "down" already exists. Looks like cheating. ;)
//...
[TypeConverter(typeof(StringArrayConverter))]
public interface IStringArray
{
int SelectedIndex { get; set; }
string[] StringArray { get; set; }
}
public class DropDownStringArray : IStringArray
{
private string[] _stringArray = { "string0", "string1", "string2", "string3", "string4", "string5", "string6" };
public int SelectedIndex { get; set; }
public string[] StringArray
{
get { return _stringArray; }
set { _stringArray = value; }
}
}
private DropDownStringArray _ddsa = new DropDownStringArray();
[Editor(typeof(StringArrayTypeEditor), typeof(UITypeEditor))]
public DropDownStringArray MyDropDownStringArray
{
get { return _ddsa; }
set { _ddsa = value; }
}
//...
public class StringArrayConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
var sa = value as IStringArray;
if (sa != null) { return sa.StringArray[sa.SelectedIndex]; }
}
return "(none)";
}
}
public class StringArrayTypeEditor : UITypeEditor
{
private IWindowsFormsEditorService _editorService;
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.DropDown; }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
_editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
DropDownStringArray ddsa = (DropDownStringArray)value;
ListBox lb = new ListBox();
lb.SelectionMode = SelectionMode.One;
for (int i = 0; i < ddsa.StringArray.Length; i++) { lb.Items.Add(ddsa.StringArray[i]); }
lb.SetSelected(ddsa.SelectedIndex, true);
lb.SelectedValueChanged += OnListBoxSelectedValueChanged;
_editorService.DropDownControl(lb);
if (lb.SelectedItem != null) { ddsa.SelectedIndex = lb.SelectedIndex; }
return value;
}
private void OnListBoxSelectedValueChanged(object sender, EventArgs e)
{
_editorService.CloseDropDown();
}
}
Which actually copy the entire class just to change the SelectedIndex. The right thing would be to abuse the SelectedIndex and convert it to a string or something like that. I think I do not care about that anymore. Rather to catch some fresh air. ;)
Maybe that will help someone else.
Note: This is not a practical propose. As example SelectedIndex will not be updated if you change the (length) of the array. I've choosen string[] because it's a really basic and well known type. I am aware that my "program" has no real use. It was just about understanding the principle.

Run function when Dictionary contents changes

I have a few ListViews that depend on the contents of Dictionary<string,string>s. I also have one function per dictionary for updating its associated ListView. However, these have to be called manually and this can cause all kinds of problems if forgotten. Is it possible to call a function whenever any value within a dictionary is changed?
My initial thoughts were to use DataBinding but Listview doesn't support this in WinForms or to raise some custom events but I wouldn't even know where to begin with that.
Is there a simple way to acheive this?
Just for clarification I'm talking about something that has this effect:
Dictionary[key] = "this"; //Automatically runs UpdateDictionaryBox();
Dictionary.Add(key,value); //The same
Dictionary.Remove(key); //And again
All credit to Tim Schmelter as his comment led me to this solution!
Essentially, the easiest method is to create a wrapper class around the Dictionary<string,string> and the ListView then use this to implement all of the dictionary methods that are needed and call the update at the end of .Add, .Remove [key] = value etc.
This way, once the class is implemented correctly, it emulates data binding.
My resulting class is:
class DictionaryListViewPseudoBinder : IEnumerable
{
private ListView ListView { get; }
private Dictionary<string,string> Dictionary { get; set; }
public DictionaryListViewPseudoBinder(ListView listView)
{
ListView = listView;
Dictionary = new Dictionary<string, string>();
}
public string this[string key]
{
get
{
return Dictionary.ContainsKey(key) ? Dictionary[key] : "";
}
set
{
if (Dictionary.ContainsKey(key))
{
Dictionary[key] = value;
RepopulateListView();
}
else
{
MessageBox.Show("Dictionary does not contain key " + key + " aborting...");
}
}
}
public void Add(string key, string value)
{
if (!Dictionary.ContainsKey(key))
{
Dictionary.Add(key, value);
RepopulateListView();
}
else
{
MessageBox.Show(string.Format("The Entry \"{0}\" already exists in {1}",key,ListView.Name));
}
}
public void Remove(string key)
{
if (Dictionary.ContainsKey(key))
{
Dictionary.Remove(key);
}
}
public bool ContainsKey(string key)
{
return Dictionary.ContainsKey(key);
}
public bool ContainsKVP(KeyValuePair<string, string> kvp)
{
if (!Dictionary.ContainsKey(kvp.Key))
{
return false;
}
else
{
return Dictionary[kvp.Key] == kvp.Value;
}
}
private void RepopulateListView()
{
ListView.Items.Clear();
foreach (KeyValuePair<string, string> kvp in Dictionary)
{
ListView.Items.Add(kvp.Key).SubItems.Add(kvp.Value);
}
}
public IEnumerator GetEnumerator()
{
return Dictionary.GetEnumerator();
}
}
NB: The above is not fully tested yet and not all methods are fully implemented at this time, but it shows the general framework necessary for this functionality.

How can I hook into all property setters of derived classes from a base class?

I have a .net web application that for all intents and purposes of this question is CRUD with many different domain objects.
A common theme across theses objects is the need to know which value properties have been modified as well as child domain model properties. Currently we have two different systems in place for this.
The value properties is the one I am trying to sort out with this question.
Right now the models all inherit from the PersistableModel base that has these fields and methods of note:
private readonly List<string> _modifiedProperties = new List<string>();
public virtual ModelState State { get; set; }
public IEnumerable<string> ModifiedProperties { get { return _modifiedProperties; } }
protected bool HasModifiedProperties { get { return 0 < _modifiedProperties.Count; } }
public bool WasModified(string propertyName)
{
return _modifiedProperties.Contains(propertyName);
}
public void WasModified(string propertyName, bool modified)
{
if (modified)
{
if (!WasModified(propertyName)) _modifiedProperties.Add(propertyName);
}
else
{
_modifiedProperties.Remove(propertyName);
}
}
Then within each individual model whenever a property is set we also need to call WasModified with a string of the property name and a boolean value.
Obviously this is very tedious and error prone, what I want to do is redesign this base class to automatically add entries to the dictionary when a derived class's property is set.
In my research the closest I've been able to get is to use PostSharp which is out of the question.
While working on a different project I came up with a solution that gets most of the way towards my original goal.
Note that this solution is reliant upon the Dev Express ViewModelBase as its base class, but it wouldn't be hard to make a new base class with the features being used for non Dev Express projects:
Edit: I found an issue with the reset state logic, this update removes that issue.
public abstract class UpdateableModel : ViewModelBase
{
private static readonly MethodInfo GetPropertyMethod;
private static readonly MethodInfo SetPropertyMethod;
private readonly bool _trackingEnabled;
private readonly Dictionary<string, Tuple<Expression, object>> _originalValues;
private readonly List<string> _differingFields;
static UpdateableModel()
{
GetPropertyMethod = typeof(UpdateableModel).GetMethod("GetProperty", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
SetPropertyMethod = typeof(UpdateableModel).GetMethod("SetProperty");
}
protected UpdateableModel(bool isNewModel)
{
_originalValues = new Dictionary<string, Tuple<Expression, object>>();
_differingFields = new List<string>();
if (isNewModel) return;
State = ModelState.Unmodified;
_trackingEnabled = true;
}
public ModelState State
{
get { return GetProperty(() => State); }
set { base.SetProperty(() => State, value); }
}
public new bool SetProperty<T>(Expression<Func<T>> expression, T value)
{
var wasUpdated = base.SetProperty(expression, value);
if (_trackingEnabled && wasUpdated)
{
UpdateState(expression, value);
}
return wasUpdated;
}
/// <summary>
/// Reset State is meant to be called when discarding changes, it will reset the State value to Unmodified and set all modified values back to their original value.
/// </summary>
public void ResetState()
{
if (!_trackingEnabled) return;
foreach (var differingField in _differingFields)
{
var type = GetFuncType(_originalValues[differingField].Item1);
var genericPropertySetter = SetPropertyMethod.MakeGenericMethod(type);
genericPropertySetter.Invoke(this, new[]{_originalValues[differingField].Item2});
}
}
/// <summary>
/// Update State is meant to be called after changes have been persisted, it will reset the State value to Unmodified and update the original values to the new values.
/// </summary>
public void UpdateState()
{
if (!_trackingEnabled) return;
foreach (var differingField in _differingFields)
{
var type = GetFuncType(_originalValues[differingField].Item1);
var genericPropertySetter = GetPropertyMethod.MakeGenericMethod(type);
var value = genericPropertySetter.Invoke(this, new object[] { _originalValues[differingField].Item1 });
var newValue = new Tuple<Expression, object>(_originalValues[differingField].Item1,value);
_originalValues[differingField] = newValue;
}
_differingFields.Clear();
State = ModelState.Unmodified;
}
private static Type GetFuncType(Expression expr)
{
var lambda = expr as LambdaExpression;
if (lambda == null)
{
return null;
}
var member = lambda.Body as MemberExpression;
return member != null ? member.Type : null;
}
private void UpdateState<T>(Expression<Func<T>> expression, T value)
{
var propertyName = GetPropertyName(expression);
if (!_originalValues.ContainsKey(propertyName))
{
_originalValues.Add(propertyName, new Tuple<Expression,object>(expression, value));
}
else
{
if (!Compare(_originalValues[propertyName].Item2, value))
{
_differingFields.Add(propertyName);
}
else if (_differingFields.Contains(propertyName))
{
_differingFields.Remove(propertyName);
}
State = _differingFields.Count == 0
? ModelState.Unmodified
: ModelState.Modified;
}
}
private static bool Compare<T>(T x, T y)
{
return EqualityComparer<T>.Default.Equals(x, y);
}
Another quick note, the IsNewModel constructor flag serves to differentiate objects create on the UI level which don't need any kind of state tracking, and objects generated from the data access level which will need the state tracking.

DataGridView List<T> column?

I have a datagridView, that is bound to a List. This List is made up of my class which contains 2 public properties, a String Name, and another List CustomList. See below:
public class MyClass2
{
public string Name
{ get; set;}
public string Description
{
get;
set;
}
}
public class MyClass
{
List<MyClass2> myList;
public string Name
{
get;
set;
}
public List<MyClass2> CustomList
{
get { return myList ?? (myList= new List<MyClass2>()); }
}
}
And then in my designer page:
List<MyClass> myClassList = new List<MyClass>();
dataGridView.DataSource = myClassList;
As it is right now, the only column that appears in the grid, is the MyClass:Name column, and the CustomList column does not show up. What I'd like is the CustomList column to show and to display something like "Collection" with the "..." button showing, and when it is clicked to have the "Collection Editor" to popup.
Does anyone know if this is possible and how to enable it? If there's a tutorial or anything that would help me out I'd appreciate that too. Thanks.
Using generics, I think, is a clean solution:
public class Sorter<T>: IComparer<T>
{
public string Propiedad { get; set; }
public Sorter(string propiedad)
{
this.Propiedad = propiedad;
}
public int Compare(T x, T y)
{
PropertyInfo property = x.GetType().GetProperty(this.Propiedad);
if (property == null)
throw new ApplicationException("El objeto no tiene la propiedad " + this.Propiedad);
return Comparer.DefaultInvariant.Compare(property.GetValue(x, null), property.GetValue(y, null));
}
}
Usage example:
string orderBy = "propertyName";
bool orderAsc = true;
List<MyExampleClass> myClassList = someMethod();
if (!string.IsNullOrEmpty(orderBy))
{
myClassList.Sort(new Sorter<MyExampleClass>(orderBy));
if (!orderAsc) myClassList.Reverse();
}
Short answer: Yes, you can do it with some code.
Long answer: To write the code is gonna be a pain in the ass, as you would have to know not only how the DataGridView behaves with custom columns, but you would need to know how to expose design time elements at runtime, which requires quite a bit of plumbing. Extensive knowledge about the PropertyGrid must also be known.
Note: This might a fun component to write. (I might actually tackle it if I get some time)
So using the 'button' approach posted by Dave, and some code that I found that implements the CollectionEditor, I can edit the CustomList in MyClass2
Here's my solution, although not quite as clean as I'd like:
Put this class somewhere:
class MyHelper : IWindowsFormsEditorService, IServiceProvider, ITypeDescriptorContext
{
public static void EditValue(IWin32Window owner, object component, string propertyName)
{
PropertyDescriptor prop = TypeDescriptor.GetProperties(component)[propertyName];
if (prop == null) throw new ArgumentException("propertyName");
UITypeEditor editor = (UITypeEditor)prop.GetEditor(typeof(UITypeEditor));
MyHelper ctx = new MyHelper(owner, component, prop);
if (editor != null && editor.GetEditStyle(ctx) == UITypeEditorEditStyle.Modal)
{
object value = prop.GetValue(component);
value = editor.EditValue(ctx, ctx, value);
if (!prop.IsReadOnly)
{
prop.SetValue(component, value);
}
}
}
private readonly IWin32Window owner;
private readonly object component;
private readonly PropertyDescriptor property;
private MyHelper(IWin32Window owner, object component, PropertyDescriptor property)
{
this.owner = owner;
this.component = component;
this.property = property;
}
#region IWindowsFormsEditorService Members
public void CloseDropDown()
{
throw new NotImplementedException();
}
public void DropDownControl(System.Windows.Forms.Control control)
{
throw new NotImplementedException();
}
public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog)
{
return dialog.ShowDialog(owner);
}
#endregion
#region IServiceProvider Members
public object GetService(Type serviceType)
{
return serviceType == typeof(IWindowsFormsEditorService) ? this : null;
}
#endregion
#region ITypeDescriptorContext Members
IContainer ITypeDescriptorContext.Container
{
get { return null; }
}
object ITypeDescriptorContext.Instance
{
get { return component; }
}
void ITypeDescriptorContext.OnComponentChanged()
{ }
bool ITypeDescriptorContext.OnComponentChanging()
{
return true;
}
PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
{
get { return property; }
}
#endregion
Add a button column to the data grid:
DataGridViewButtonColumn butt = new DataGridViewButtonColumn();
butt.HeaderText = "CustomList";
butt.Name = "CustomList";
butt.Text = "Edit CustomList...";
butt.UseColumnTextForButtonValue = true;
dataGridView.Columns.Add(butt);
dataGridView.CellClick += new DataGridViewCellEventHandler(dataGridView_CellClick);
Then call it in the button handler of the cell click.
if (e.RowIndex < 0 || e.ColumnIndex != dataGridView.Columns["CustomList"].Index)
return;
//get the name of this column
string name = (string)dataGridView[dataGridView.Columns["Name"].Index, e.RowIndex].Value;
var myClassObject= myClassList.Find(o => o.Name == name);
MyHelper.EditValue(this, myClassObject, "CustomList");
I'd still be interested in hearing other approaches, and not having to implement my own CollectionEditor. And I'm still interested in having it look more like what the TabControl uses to add TabPages in the PropertyGrid...by displaying the "..." button...but this might work for now.
What you want to do is add a column template with a button in it:
http://geekswithblogs.net/carmelhl/archive/2008/11/11/126942.aspx
In the handler for the button, get the selected MyClass item from the collection and bind its list property to a grid in your popup.

Cast with GetType()

Is it possible to cast an object to the type returned from GetType()? I'd like a generic method that can accept an object (for anonymous types) but then return an object cast as the anonymous type. I've been thinking of using the LCG DynamicMethod to build a method on a container class, but I can't exactly figure out what that would look like. The idea to cast with the GetType() method was to be able to get the anonymous type and cast an object to its actual type without actually knowing the type.
The overarching goal is to stick anonymous-typed objects into a container, that I could then share and pass between methods.
I can't think of why you'd want to cast as GetType(), because you wouldn't be able to do anything to useful with the result, without knowing the type at compile time anyway.
Perhaps what you are looking for, is being able to Convert. If that is the case, the following should work for you:
object input = GetSomeInput();
object result = Convert.ChangeType(input, someOtherObject.GetType());
We use this when reading values from the registry which are all stored as strings, and then stuffing them into properties using reflection.
Your intent is very unclear; however, one option is generics and MakeGenericMethod in particular. What do you want to do with this? For example:
static class Program
{
static void Main()
{
object obj = 123.45;
typeof(Program).GetMethod("DoSomething")
.MakeGenericMethod(obj.GetType())
.Invoke(null, new object[] { obj });
}
public static void DoSomething<T>(T value)
{
T item = value; // well... now what?
}
}
So now we have the value, typed as double via generics - but there still isn't much we can do with it except for calling other generic methods... what was it you want to do here?
You can use the Activator.CreateInstance method to create an instance from a type.
FYI reflection is SLOOWWWW, so if you need to do this cast many times in a row, it may be better to define your types in an enum or something like this then create instances without using reflection.
I have a class that I use for change tracking in my Windows Forms app because not all items were databound. Most items were TextBox controls, but there were ComboBox and DateTimePicker controls as well.
For simplicity, my HasChanged property tests the generic Windows.Forms.Control to see if it is a ComboBox, but you could test whatever types of controls you add to your Windows Form.
Below is that class - if it helps for anyone.
internal class DataItem
{
private static Color originalBackColor, changedBackColor, originalForeColor, changedForeColor;
private static Font originalFont, changedFont;
static DataItem()
{
originalBackColor = SystemColors.Control;
changedBackColor = SystemColors.HighlightText;
originalForeColor = Color.Black;
changedForeColor = Color.Red;
originalFont = new Font(FontFamily.GenericSansSerif, 12.5f);
changedFont = new Font(originalFont, FontStyle.Bold);
}
public static void ChangeSetup(Control original, Color changedBackgroundColor)
{
originalBackColor = original.BackColor;
originalForeColor = original.ForeColor;
originalFont = original.Font;
changedBackColor = changedBackgroundColor;
changedFont = new Font(originalFont, FontStyle.Bold);
}
private bool changeTracking;
public DataItem(Control control, Object value)
{
this.Control = control;
var current = String.Format("{0}", Control.Text).Trim();
if (Control is ComboBox)
{
var cbo = (ComboBox)Control;
current = cbo.StateGet();
}
this.OriginalValue = current;
this.Control.TextChanged += Control_TextChanged;
changeTracking = true;
}
public Control Control { get; private set; }
private void Control_TextChanged(Object sender, EventArgs e)
{
if (TrackingChanges)
{
if (HasChanged)
{
this.Control.BackColor = originalBackColor;
this.Control.Font = originalFont;
this.Control.ForeColor = originalForeColor;
}
else
{
this.Control.BackColor = changedBackColor;
this.Control.Font = changedFont;
this.Control.ForeColor = changedForeColor;
}
}
}
public bool HasChanged
{
get
{
var current = String.Format("{0}", Control.Text).Trim();
if (Control is ComboBox)
{
var cbo = (ComboBox)Control;
current = cbo.StateGet();
}
return !current.Equals(OriginalValue);
}
}
public String OriginalValue { get; private set; }
public void Reset()
{
changeTracking = false;
this.OriginalValue = String.Empty;
this.Control.Text = String.Empty;
this.Control.BackColor = originalBackColor;
this.Control.Font = originalFont;
this.Control.ForeColor = originalForeColor;
}
public bool TrackingChanges
{
get
{
return changeTracking;
}
}
}
You can use getClass() which returns a Class object then use the cast method in the Class object to cast the object to an object of that Class's type, like so:
myObj.getClass().cast(myObj)

Categories

Resources