How does ^ (handle to object operator) works? - winforms

I can remove last char from textBox by
textBox1->Text = textBox1->Text->Remove(textBox1->Text->Length - 1);
And I want to do it creating a reference or a pointer to the Text. But I can't do it like this
String^ t = textBox1->Text;
t = t->Remove(t->Length - 1); // Text doesn't change
P.S. Any of this doesn't compile:
String* t = textBox1->Text; // error: an ordinary pointer to a
// C++/CLI ref class or interface class
// is not allowed
String& t = textBox1->Text; // error: an ordinary reference to a
// C++/CLI ref class or interface class
// is not allowed
String% t = textBox1->Text // error: a tracking reference to a
// System::String is not allowed

t = t->Remove(t->Length - 1);
just changes the local reference (pointer-thingy, handle, …) t, to refer to the string returned by Remove.
The textbox string isn't changed by that.
When you do
textBox1->Text = t;
… you're calling a setter function for the property Text, and this setter function not just changes the textbox string data, but updates or at least invalidates the textbox display.

Related

How do you determine (WinForms) control type in UITestControl?

I'm trying to make custom properties for controls available in Coded UI Tests and every example I've found is totally useless.
For instance: http://msdn.microsoft.com/en-us/library/hh552522.aspx
public override int GetControlSupportLevel(UITestControl uiTestControl)
{
// For MSAA, check the control type
if (string.Equals(uiTestControl.TechnologyName, "MSAA",
StringComparison.OrdinalIgnoreCase) &&
(uiTestControl.ControlType == "Chart"||uiTestControl.ControlType == "Text"))
{
return (int)ControlSupport.ControlSpecificSupport;
}
// This is not my control, so return NoSupport
return (int)ControlSupport.NoSupport;
}
// Get the property value by parsing the accessible description
public override object GetPropertyValue(UITestControl uiTestControl, string propertyName)
{
if (String.Equals(propertyName, "State", StringComparison.OrdinalIgnoreCase))
{
object[] native = uiTestControl.NativeElement as object[];
IAccessible acc = native[0] as IAccessible;
string[] descriptionTokens = acc.accDescription.Split(new char[] { ';' });
return descriptionTokens[1];
}
// this is not my control
throw new NotSupportedException();
}
This code is entirely worthless if you have 2 different controls that are "Text" controls - there is no way to determine which type of text control it is. The "ControlType" property is very misleading because it does not return the Type of the control as its name suggests. It's more like a control category. How can you determine what the control actually is?
You can use something like this. Hope this helps.
string controlType = control.GetProperty(XamlControl.PropertyNames.ControlType).ToString();

When Deep Copying a WPF Data Bound Object

I wrote a nifty method to deep copy any object. It does so by recursively calling MemberwiseClone() on any reference type field inside the instance. This method works perfectly on any object I care to use it, including hierarchy relationship objects. The method also sports a dictionary of past visitations so unnecessary duplicate work is avoided.
The problem I am having, however, is that this method only works when the object is NOT data bound to WPF/MVVM when a clone is needed. When data bound and the method is invoked, I run into stack overflow exceptions because of (I assume) an established link between INotifyPropertyChanged.PropertyChanged event and the WPF framework. The recursive call then attempts to copy the entire universe of objects including the AppDomain and low-level Pointer objects, which appear to be linked and go on to almost infinity (more than VS2012 can handle, anyway.)
I doubt I will ever have need to deep copy an object graph that goes back to the beginning of the AppDomain... is there a smart way to have my copy method "stop" when it reaches a certain boundary? I also thought about simply copying objects before they're data bound, but I'm not sure that's a feasible option, and it's rather silly. I just want a simple deep copy solution that works on types that are not serializable, but are also data-bound via INotifyPropertyChanged.
The method's implementation:
private static object Clone(object instance, IDictionary<object, object> visitGraph)
{
var instanceType = instance.GetType();
Debug.WriteLine(instanceType.Name);
object clonedInstance = null;
if (visitGraph.ContainsKey(instance))
{
clonedInstance = visitGraph[instance];
}
else
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance;
var memberwiseCloneMethod =
instanceType.GetMethods(flags).Single(x => x.Name == "MemberwiseClone" &&
!x.GetParameters().Any());
clonedInstance = memberwiseCloneMethod.Invoke(instance, null);
visitGraph.Add(instance, clonedInstance);
var allReferenceTypeProperties = clonedInstance.GetType().GetAllFields()
.Where(
x =>
!x.FieldType.IsValueType
&& x.FieldType != typeof (string));
foreach (var field in allReferenceTypeProperties)
{
var existingFieldValue = field.GetValue(instance);
if (existingFieldValue != null)
{
var clonedFieldValue = Clone(existingFieldValue, visitGraph);
field.SetValue(clonedInstance, clonedFieldValue);
}
}
}
return clonedInstance;
}
public static IEnumerable<FieldInfo> GetAllFields(this Type type)
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance;
var fields = type.GetFields(flags);
foreach (var field in fields)
{
yield return field;
}
if (type.BaseType != null)
{
foreach (var field in GetAllFields(type.BaseType))
{
yield return field;
}
}
}
public static object Copy(this object instance)
{
if (instance == null) throw new ArgumentNullException("instance");
var visitGraph = new Dictionary<object, object>();
var clonedInstance = Clone(instance, visitGraph);
return clonedInstance;
}
I'm answering my own question with a shortcut solution. I would much prefer a permanent solution, but I haven't the luxury.
I modified my deep clone method to shallow (instead of deep) copy EventHandler objects. The objects are no longer a true deep clone, but that's not a problem for my application. Still, I would like a solution that applies in all situations.

Flex - Objects within Objects

So I'm still trying to get my head around Flex and OOP and I am stuck right now. Here is the code I'm currently working with.
var labs:ArrayCollection = new ArrayCollection();
var sets:ArrayCollection = new ArrayCollection();
var labsArray:Array = ["ProDPI","WHCC","Tin"];
var setsArray:Array = [ ["Set01","Set02","Set03","Set04"],["Set11","Set12","Set13","Set14"], ["Set21","Set22","Set23","Set24"] ];
var objLab:Object = new Object;
objLab.labName = labsArray[0];
objLab.setFolders = undefined;
labs.addItem(objLab);
for (var i:int = 0; i < setsArray.length; i++) {
var objSets:Object = new Object;
objSets.setName = setsArray[i];
sets.addItem(objSets);
objLab.setFolders = objSets;
}
labFolderList.labelField="labName";
labFolderList.dataProvider=labs;
setFolderList.labelField="setFolders";
setFolderList.dataProvider=sets;
The objLab object is returning as I wish it to. The objSets is displaying in my ComboBox as object, Object. The application is ComboBox #1 will be populated by labsArray, which is working. Depending on the selection of [0,1,2] from the array this will call from the sets array the array in the matching position.
Finally, with the selection of the ComboBox#1, the second ComboBox#2 will change to the matching selection.
Any help on how to get the object Objects to rendering correctly would be of great help. Also if my execution is not the best way to do this any direction (links/documentation) I will take as well. Thanks in advance.
I edited your original code based on assumptions for what you were trying to accomplish, I added the Array objects directly to the collection being assigned the dataprovider, in this case you should see the output of the .toString() method called on the Array instead of the Object class, the Object class .toString() will output the [object Object] you were seeing in the display. The Array .toString() method will call .toString() on each element in the array and separate them with commas and surround them with curly braces, very similar to what you have when defining the array. Alternatively you could create your own class that extends Object and make your own toString method to override the default behavior, using Object is generally not a great practice (there are exceptions to this it's not a hard rule but it tends to be better to use a specific class type, or even better an interface when possible).
var labs:ArrayCollection = new ArrayCollection();
var sets:ArrayCollection = new ArrayCollection();
var labsArray:Array = ["ProDPI","WHCC","Tin"];
var setsArray:Array = [ ["Set01","Set02","Set03","Set04"],["Set11","Set12","Set13","Set14"], ["Set21","Set22","Set23","Set24"] ];
var objLab:Object = new Object;
objLab.labName = labsArray[0];
objLab.setFolders = undefined;
labs.addItem(objLab);
for (var i:int = 0; i < setsArray.length; i++) {
sets.addItem(setsArray[i]);
objLab.setFolders = setsArray[i];
}
labFolderList.labelField="labName";
labFolderList.dataProvider=labs;
setFolderList.labelField="setFolders";
setFolderList.dataProvider=sets;
Another alternative aside from making a Class as I explained above is to use the labelFunction instead of the labelField, using a labelFunction each item:Object in the dataProvider will be passed into your custom labelFunction and you can return a string based on whatever logic you see fit. It would be something along these lines:
setFolderList.labelFunction = myLabelFunction;
private function myLabelFunction(item:Object):String
{
var retString:String = "";
for(var i:int=0; i<item.setName.length; i++)
{
if(i>0)
retString += ", ";
retString += item.setName[i];
}
return retString;
}

null reference exception error for my windows form app

I have a Setting.cs file containing the info
[Serializable]
public class Setting
{
public Setting() {}
public String defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\applause-2.wav";
}
and my settingsForm retrieving the info through this code
Setting settingObject;
public SoundPlayer player;
public settingsForm(backgroundForm backgroundFormObject)
{
InitializeComponent();
this.backgroundFormObject = backgroundFormObject;
settingObject = backgroundFormObject.getSetting();
}
private void InitializeSound()
{
// Create an instance of the SoundPlayer class.
player = new SoundPlayer();
player.SoundLocation = settingObject.defaultAlertTone;
// Listen for the LoadCompleted event.
player.LoadCompleted += new AsyncCompletedEventHandler(player_LoadCompleted);
// Listen for the SoundLocationChanged event.
player.SoundLocationChanged += new EventHandler(player_LocationChanged);
}
Why is it that every time I run the app, there would be a null reference exception on the
player.SoundLocation = settingObject.defaultAlertTone;
the backgroundFormObject.getSetting(); is just a method to retrieve the setting object. the code for it are as follows
Setting settingObj = new Setting();
public Setting getSetting()
{
return settingObj;
}
The reasons could be
InitializeSound() is somehow running before settingsForm (not likely, but this would make the settingObject not initialized and refer to null).
If this is the complete code for Setting class, i don't see how calling new Setting() anywhere would make a difference. So use Setting settingObject = new Setting(); when you first define this property in the settingsForm class.
It is not the settingObject which is null.

WPF RichTextbox remove Foreground information from TextRange

sorry for my bad english... The default for a RichTextBox content is to inherit the Foreground color from the RichTextBox itself. That's nice, but if I set a specific Foreground color to some part of my text, that part does not inherit the Foreground anymore, obviously. How can I make my "colored" text inherit the Foreground again? I'm trying to do something like the "Automatic" color from Office Word but after I have set a specific color to a TextRange, I do not know how to unset it :/
TextRange.ClearAllProperties() does what I need, but also erases other properties like FontSize and FontFamily...
TextRange.ApplyPropertyValue(ForegroundProperty, DependencyProperty.UnsetValue) also does not do the trick...
You can also unset it by setting the property to null (this worked for me clearing out the background, for example removing highlighting)
TextRange.ApplyPropertyValue(TextElement.BackgroundProperty, null);
This seemed almost impossible to achieve since there is no "RemovePropertyValue" method. I also tried with span and got the same exception as you did so I made a method that collects all the Paragraphs within the TextRange and made a span for each separetly.. less than ideal, I know.. Anyway, it works for a small example but might be pretty hard to work with for something more complex.
private List<Span> m_spanList = new List<Span>();
private void c_setForegroundButton_Click(object sender, RoutedEventArgs e)
{
TextPointer textPointerStart = c_richTextBox1.Selection.Start;
TextPointer textPointerEnd = c_richTextBox1.Selection.End;
TextRange textRange = new TextRange(textPointerStart, textPointerEnd);
SetForeground(textRange);
}
private void c_clearForegroundButton_Click(object sender, RoutedEventArgs e)
{
foreach (Span span in m_spanList)
{
span.ClearValue(Span.ForegroundProperty);
}
}
public void SetForeground(TextRange textRange)
{
List<Paragraph> spannedParagraphs = new List<Paragraph>();
if (textRange.Start.Paragraph != null)
{
TextRange curRange = null;
Block cur = textRange.Start.Paragraph;
do
{
spannedParagraphs.Add(cur as Paragraph);
// Get next range
curRange = new TextRange(cur.ContentStart, cur.ContentEnd);
} while ((textRange.End.Paragraph == null || !curRange.Contains(textRange.End.Paragraph.ContentEnd)) && (cur = cur.NextBlock) != null);
}
if (spannedParagraphs.Count == 1)
{
Span span = new Span(c_richTextBox1.Selection.Start, c_richTextBox1.Selection.End);
span.Foreground = Brushes.Red;
m_spanList.Add(span);
}
else
{
for (int i = 0; i < spannedParagraphs.Count; i++)
{
if (i == spannedParagraphs.Count - 1)
{
Paragraph paragraph = spannedParagraphs[i];
// For some reason I get an exception here when I try this..
//m_span = new Span(paragraph.ElementStart, c_richTextBox1.Selection.End);
c_richTextBox1.Selection.Select(paragraph.ElementStart, c_richTextBox1.Selection.End);
Span span = new Span(c_richTextBox1.Selection.Start, c_richTextBox1.Selection.End);
span.Foreground = Brushes.Red;
m_spanList.Add(span);
}
else if (i == 0)
{
Paragraph paragraph = spannedParagraphs[i];
Span span = new Span(c_richTextBox1.Selection.Start, paragraph.ElementEnd);
span.Foreground = Brushes.Red;
m_spanList.Add(span);
}
else
{
Paragraph paragraph = spannedParagraphs[i];
Span span = new Span(paragraph.ElementStart, paragraph.ElementEnd);
span.Foreground = Brushes.Red;
m_spanList.Add(span);
}
}
}
}
If you look at the code of method TextRange.ApplyPropertyValue in the .NET Reference Source, you'll see that in the end it calls DependencyObject.SetValue on a collection of Inlines and Blocks, and DependencyObject.SetValue treats the value DependencyProperty.UnsetValue specially by effectively clearing the local value for the property.
The problem is that they didn't think of that when implementing TextRange.ApplyPropertyValue: it checks the passed property value against the property type, and in case of a reference type, it makes sure the passed value is either null or inherits from the same class, thus preventing us from passing DependencyProperty.UnsetValue.
One solution I found to implement a way of clearing local values of a TextRange for dependency properties of a reference type is the following:
// We declare a marker brush to be detected later in the TextRange.
var markerBrush = new SolidColorBrush();
// First we ask the TextRange implementation to set our marker brush on its content.
// Using ApplyPropertyValue here takes care of splitting inlines when necessary to make
// sure that only the selected text gets affected.
range.ApplyPropertyValue(TextElement.ForegroundProperty, markerBrush);
// Now, we search the text range for every Inline that has our brush set as the foreground
// brush, and we clear the Foreground dependency property.
var position = range.Start;
while (position != null && range.Contains(position))
{
if (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart &&
position.Parent is Inline inline &&
inline.ReadLocalValue(TextElement.ForegroundProperty) == _foregroundClearBrush)
inline.ClearValue(TextElement.ForegroundProperty);
position = position.GetNextContextPosition(LogicalDirection.Forward);
}

Resources