I'm trying to get a control by name. I wrote the following code:
public Control GetControlByName(string name)
{
Control currentControl;
for(int i = 0,count = Controls.Count; i < count; i++)
{
currentControl = Controls[i];
if (currentControl.HasChildren)
{
while (currentControl.HasChildren)
{
for(int x = 0,size = currentControl.Controls.Count; x < size; x++)
{
currentControl = currentControl.Controls[x];
if (currentControl.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
return currentControl;
}
}
}
}
else
{
if (currentControl.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
{
return currentControl;
}
}
}
return null;
}
It only ever returns null. Can someone point out my mistake? Any help or ways to improve this code are welcomed.
Just use the Controls collection Find method:
var aoControls = this.Controls.Find("MyControlName", true);
if ((aoControls != null) && (aoControls.Length != 0))
{
Control foundControl = aoControls[0];
}
I actually wrote some extension methods at work to do just this thing:
public static class MyExensions ()
{
public static Control FindControlRecursively (this Control control, string name)
{
Control result = null;
if (control.ID.Equals (name))
{
result = control;
}
else
{
foreach (var child in control.Children)
{
result = child.FindControlRecursively (name);
if (result != null)
{
break;
}
}
}
return result;
}
public static T FindControlRecursively<T> (this Control control, string name)
where T: Control
{
return control.FindControlRecursively (name) as T;
}
}
Note: Null checks removed for the sake of simplicity.
You can use it to find, say, a TextBox on your form like so:
public class MyForm : Form
{
public void SetSomeText ()
{
var control = this.FindControlRecursively<TextBox> ("myTextboxName");
if (control != null)
{
control.Text = "I found it!";
}
// Or...
var control2 = this.FindControlRecursively ("myTextboxName2") as TextBox;
if (control != null)
{
control2.Text = "I found this one, also!";
}
}
}
Edit
Of course, this is a depth-first algorithm, which might be slow depending on how deep your control chain is. You might rewrite it to use a breadth-first algorithm if you see that it is too slow.
A slight tweak for if you're not using System.Windows.Forms (this is what .Find(string, bool) works off too)
public static class MyExensions
{
public static Control FindControlRecursively(this Control control, string name)
{
Control result = null;
if (control.ID.Equals(name))
{
result = control;
}
else
{
for (var i = 0; i < control.Controls.Count; i++)
{
result = control.Controls[i].FindControlRecursively(name);
if (result != null)
{
break;
}
}
}
return result;
}
public static T FindControlRecursively<T>(this Control control, string name)
where T : Control
{
return control.FindControlRecursively(name) as T;
}
}
p.s. Yes I know it's an old question, but in case it helps 😁
Related
I'm stuck with some legacy code that I want to upgrade a bit. I want to change the way the ErrorProvider shows the error status on a Control. Default behavior is the Icon, and a ToolTip if you hover on the icon.
I would like to change this behavior to be more similar to what we use in our WPF controls. Which is a red back-color(Salmon pink) and the tool-tip on the control itself.
Any tips, links or some way forward
EDIT.
See my answer below, on what i ended up with.
ErrorProvider component doesn't support this feature and if you need it you can create it yourself.
You can subscribe to BindingComplete event of a BindingManagerBase and then you can use the event arg which is of type BindingCompleteEventArgs that contains some useful properties:
ErrorText to determine if there is an error in data-binding
Binding.Control to determine the control which is bounded to
These are enough for us to implement our solution.
Code
Here is a sample code which shows how can you handle BindingComplete event and use it to change BackColor and tool-tip of a control based on it's valid or invalid state.
Suppose you have a binding source, myBindingSource which is bound to a SampleModel class which is implemented IDataErrorInfo. You can subscribe to BindingComplete event of this.BindingContext[this.myBindingSource]:
private void Form1_Load(object sender, EventArgs e)
{
this.myBindingSource.DataSource = new SampleModel();
var bindingManager = this.BindingContext[this.myBindingSource];
bindingManager.BindingComplete += bindingManager_BindingComplete;
}
Dictionary<Control, Color> Items = new Dictionary<Control, Color>();
private void bindingManager_BindingComplete(object sender, BindingCompleteEventArgs e)
{
var control = e.Binding.Control;
//Store Original BackColor
if (!Items.ContainsKey(control))
Items[control] = control.BackColor;
//Check If there is an error
if (!string.IsNullOrEmpty(e.ErrorText))
{
control.BackColor = Color.Salmon;
this.errorToolTip.SetToolTip(control, e.ErrorText);
}
else
{
e.Binding.Control.BackColor = Items[e.Binding.Control];
this.errorToolTip.SetToolTip(control, null);
}
}
Thank you Reza Aghaei. This is what i came up with based on your comment and some additional searching... Some of this code comes from msdn resource
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ErrorProvider
{
class BackgroundColorErrorProvider: Component, IExtenderProvider, ISupportInitialize
{
public BackgroundColorErrorProvider()
{
currentChanged = new EventHandler(ErrorManager_CurrentChanged);
}
public BackgroundColorErrorProvider(ContainerControl parentControl)
: this()
{
this.parentControl = parentControl;
propChangedEvent = new EventHandler(ParentControl_BindingContextChanged);
parentControl.BindingContextChanged += propChangedEvent;
}
public BackgroundColorErrorProvider(IContainer container)
: this()
{
if (container == null) {
throw new ArgumentNullException("container");
}
container.Add(this);
}
public bool CanExtend(object extendee)
{
return extendee is Control && !(extendee is Form) && !(extendee is ToolBar);
}
private bool inSetErrorManager = false;
private object dataSource;
private string dataMember = null;
private ContainerControl parentControl;
private BindingManagerBase errorManager;
private bool initializing;
private EventHandler currentChanged;
private EventHandler propChangedEvent;
private Dictionary<Control, Color> originalColor = new Dictionary<Control, Color>();
private Color errorBackgroundColor;
public ContainerControl ContainerControl
{
[UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
[UIPermission(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
get
{
return parentControl;
}
set
{
if (parentControl != value)
{
if (parentControl != null)
parentControl.BindingContextChanged -= propChangedEvent;
parentControl = value;
if (parentControl != null)
parentControl.BindingContextChanged += propChangedEvent;
Set_ErrorManager(this.DataSource, this.DataMember, true);
}
}
}
public string DataMember
{
get { return dataMember; }
set
{
if (value == null) value = "";
Set_ErrorManager(this.DataSource, value, false);
}
}
public object DataSource
{
get { return dataSource; }
set
{
if ( parentControl != null && value != null && String.IsNullOrEmpty(this.dataMember))
{
// Let's check if the datamember exists in the new data source
try
{
errorManager = parentControl.BindingContext[value, this.dataMember];
}
catch (ArgumentException)
{
// The data member doesn't exist in the data source, so set it to null
this.dataMember = "";
}
}
Set_ErrorManager(value, this.DataMember, false);
}
}
public override ISite Site
{
set
{
base.Site = value;
if (value == null)
return;
IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host != null)
{
IComponent baseComp = host.RootComponent;
if (baseComp is ContainerControl)
{
this.ContainerControl = (ContainerControl)baseComp;
}
}
}
}
private ToolTip toolTip;
public ToolTip ToolTip
{
get { return toolTip; }
set { toolTip = value; }
}
public Color ErrorBackgroundColor
{
get { return errorBackgroundColor; }
set { errorBackgroundColor = value; }
}
private void Set_ErrorManager(object newDataSource, string newDataMember, bool force)
{
if (inSetErrorManager)
return;
inSetErrorManager = true;
try
{
bool dataSourceChanged = this.DataSource != newDataSource;
bool dataMemberChanged = this.DataMember != newDataMember;
//if nothing changed, then do not do any work
//
if (!dataSourceChanged && !dataMemberChanged && !force)
{
return;
}
// set the dataSource and the dataMember
//
this.dataSource = newDataSource;
this.dataMember = newDataMember;
if (!initializing)
{
UnwireEvents(errorManager);
// get the new errorManager
//
if (parentControl != null && this.dataSource != null && parentControl.BindingContext != null)
{
errorManager = parentControl.BindingContext[this.dataSource, this.dataMember];
}
else
{
errorManager = null;
}
// wire the events
//
WireEvents(errorManager);
// see if there are errors at the current
// item in the list, w/o waiting for the position to change
if (errorManager != null)
UpdateBinding();
}
}
finally
{
inSetErrorManager = false;
}
}
public void UpdateBinding()
{
ErrorManager_CurrentChanged(errorManager, EventArgs.Empty);
}
private void UnwireEvents(BindingManagerBase listManager)
{
if (listManager != null)
{
listManager.CurrentChanged -= currentChanged;
listManager.BindingComplete -= new BindingCompleteEventHandler(this.ErrorManager_BindingComplete);
CurrencyManager currManager = listManager as CurrencyManager;
if (currManager != null)
{
currManager.ItemChanged -= new ItemChangedEventHandler(this.ErrorManager_ItemChanged);
currManager.Bindings.CollectionChanged -= new CollectionChangeEventHandler(this.ErrorManager_BindingsChanged);
}
}
}
private void WireEvents(BindingManagerBase listManager)
{
if (listManager != null)
{
listManager.CurrentChanged += currentChanged;
listManager.BindingComplete += new BindingCompleteEventHandler(this.ErrorManager_BindingComplete);
CurrencyManager currManager = listManager as CurrencyManager;
if (currManager != null)
{
currManager.ItemChanged += new ItemChangedEventHandler(this.ErrorManager_ItemChanged);
currManager.Bindings.CollectionChanged += new CollectionChangeEventHandler(this.ErrorManager_BindingsChanged);
}
}
}
private void ErrorManager_BindingsChanged(object sender, CollectionChangeEventArgs e)
{
ErrorManager_CurrentChanged(errorManager, e);
}
private void ParentControl_BindingContextChanged(object sender, EventArgs e)
{
Set_ErrorManager(this.DataSource, this.DataMember, true);
}
private void ErrorManager_ItemChanged(object sender, ItemChangedEventArgs e)
{
BindingsCollection errBindings = errorManager.Bindings;
int bindingsCount = errBindings.Count;
// If the list became empty then reset the errors
if (e.Index == -1 && errorManager.Count == 0)
{
for (int j = 0; j < bindingsCount; j++)
{
if ((errBindings[j].Control != null))
{
// ...ignore everything but bindings to Controls
SetError(errBindings[j].Control, "");
}
}
}
else
{
ErrorManager_CurrentChanged(sender, e);
}
}
private void SetError(Control control, string p)
{
if (String.IsNullOrEmpty(p))
{
if (originalColor.ContainsKey(control))
control.BackColor = originalColor[control];
toolTip.SetToolTip(control, null);
}
else
{
control.BackColor = ErrorBackgroundColor;
toolTip.SetToolTip(control, p);
}
}
private void ErrorManager_BindingComplete(object sender, BindingCompleteEventArgs e)
{
Binding binding = e.Binding;
if (binding != null && binding.Control != null)
{
SetError(binding.Control, (e.ErrorText == null ? String.Empty : e.ErrorText));
}
}
private void ErrorManager_CurrentChanged(object sender, EventArgs e)
{
if (errorManager.Count == 0)
{
return;
}
object value = errorManager.Current;
if (!(value is IDataErrorInfo))
{
return;
}
BindingsCollection errBindings = errorManager.Bindings;
int bindingsCount = errBindings.Count;
// We can only show one error per control, so we will build up a string...
//
Hashtable controlError = new Hashtable(bindingsCount);
for (int j = 0; j < bindingsCount; j++)
{
// Ignore everything but bindings to Controls
if (errBindings[j].Control == null)
{
continue;
}
string error = ((IDataErrorInfo)value)[errBindings[j].BindingMemberInfo.BindingField];
if (error == null)
{
error = "";
}
string outputError = "";
if (controlError.Contains(errBindings[j].Control))
outputError = (string)controlError[errBindings[j].Control];
// VSWhidbey 106890: Utilize the error string without including the field name.
if (String.IsNullOrEmpty(outputError))
{
outputError = error;
}
else
{
outputError = string.Concat(outputError, "\r\n", error);
}
controlError[errBindings[j].Control] = outputError;
}
IEnumerator enumerator = controlError.GetEnumerator();
while (enumerator.MoveNext())
{
DictionaryEntry entry = (DictionaryEntry)enumerator.Current;
SetError((Control)entry.Key, (string)entry.Value);
}
}
public void BeginInit()
{
initializing = true;
}
public void EndInit()
{
initializing = false;
Set_ErrorManager(this.DataSource, this.DataMember, true);
}
}
}
void Visualize(object CoreObj, object ParentControl)
{
if(CoreObj is typeA)
{
object control1 = new MyControl1(CoreObj);
ParentControl.FirstChild.Children.Add(control1);
foreach (object obj in CoreObj.Children)
{
Visualize(obj, control1);
}
}
else if (CoreObj is typeB)
{
object control2 = new MyControl2(CoreObj);
ParentControl.FirstChild.Children.Add(control2);
foreach (object obj in CoreObj.Children)
{
Visualize(obj, control2);
}
}
}
Where FirstChild is always container, no matter StackPanel, Grid or Canvas, or whatever.
How I get the first child, and the harder part, how to do Children.Add() on object?
I can require something else in case "Children" is inherited from somewhere in all wpf containers, but I can't find out which ancestor/interface contains "Children". Or I can use Reflection probably..
How to do this?
Here's what I came with, finally
interface IContain
{
Panel GetMain(); //return main container
}
// ...
void Visualize(object CoreObj, Panel ParentControl)
{
UIElement control = new UIElement();
if (CoreObj is File) { control = new NameSpacer(); } //new NameSpacer(obj);
else if (CoreObj is Namespace) { control = new NameSpacer(); }
else if(CoreObj is Using) { control = new NameSpacer(); }
if (control.GetType() == typeof(UIElement)) return;
ParentControl.Children.Add(control);
FieldInfo finf = CoreObj.GetType().GetField("Children"); if (finf == null) return;
var val = finf.GetValue(CoreObj); if (val.GetType() != typeof(IEnumerable<object>)) return;
if (control is IContain == false) return;
Panel container = ((IContain)control).GetMain();
foreach (object o in val as IEnumerable<object>)
{
Visualize(o, container);
}
}
You can use VisualTreeHelper class to get the first child.
Children property is defined in abstract class Panel.
var firstChild = parentControl.Descendants().OfType<Panel>().First();
firstChild.Children.Add(control1);
The descendants method leverages VisualTreeHelper in order to get all descendants and you have to define it as extension method:
public static IEnumerable<DependencyObject> Descendants(this DependencyObject element)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < childrenCount; i++)
{
var visualChild = VisualTreeHelper.GetChild(element, i);
yield return visualChild;
foreach (var visualChildren in Descendants(visualChild))
{
yield return visualChildren;
}
}
}
StackPanel, Grid and Canvas, all derive from the Panel class. This is also the class that contains the Children property.
if you know your argument is a Panel, you also have access to Children.First() and Children.Add(..)
I created a UserControl that has a FlowLayoutPanel on it. I populate this panel in runtime with a CollectionBase of PictureBoxes. I then have a FlowLayoutPanel on my WindowsForm that I populate in runtime using a CollectionBase of my UserControls.
Now, I want to be able to access a custom function within my UserControl in order to add another PictureBox to an instanciated (existing) UserControl's FlowLayoutPanel. How do I access the function to do this?
The function is public within the UserControl but I am unable to get through the CollectionBase in order to use it.
Here is my code for the UserControl:
public partial class UserDisplay : UserControl
{
public UserDisplay()
{
InitializeComponent();
myEquipArray = new ImageArray(flpnlTools);
}
public void AddEquip(string EquipName, Image EquipImage)
{
myEquipArray.AddNewEquip(EquipName, EquipImage);
}
//Accessor
public ControlCollection Equips
{
get
{
return flpnlEquips.Controls;
}
}
}
public class ImageArray : System.Collections.CollectionBase
{
private readonly System.Windows.Forms.FlowLayoutPanel HostPanel;
public ImageArray(FlowLayoutPanel hostPanel)
{
HostPanel = hostPanel;
}
public System.Windows.Forms.PictureBox AddNewEquip(string EquipName, Image EquipImage)
{
PictureBox pbA = new PictureBox();
this.List.Add(pbA);
HostPanel.Controls.Add(pbA);
pbA.Tag = EquipName;
pbA.Image = EquipImage;
return pbA;
}
public void RemoveEquip(string EquipName)
{
if (this.Count > 0)
{
int i = 0;
while (EquipName != HostPanel.Controls[i].Tag.ToString())
{
i++;
}
HostPanel.Controls.Remove(this[EquipName]);
this.List.RemoveAt(i);
}
}
public PictureBox this[string EquipName]
{
get
{
int i = 0;
while (EquipName != HostPanel.Controls[i].Tag.ToString())
{
i++;
}
return (PictureBox)this.List[i];
}
}
}
I use this Class to implement the UserConrol on my WindowsForm:
public class UserDsp : System.Collections.CollectionBase
{
private readonly System.Windows.Forms.FlowLayoutPanel HostPanel;
public DisplayControl.UserDisplay AddNewUser(Int64 UserID, string UserName, Image UserImage, string EquipName, Image EquipImage)
{
DisplayControl.UserDisplay newUser = new DisplayControl.UserDisplay();
this.List.Add(newUser);
HostPanel.Controls.Add(newUser);
newUser.Tag = UserID;
newUser.UserName = UserName;
newUser.UserImage = UserImage;
newUser.AddEquip(EquipName, EquipImage); //THIS ADDS THE PICTUREBOX CORRECTLY
return newUser;
}
public void AddNewEquip(Int64 UserID, Int64 EquipID, string EquipName, Image EquipImage)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
// Found the Control with UserID
HostPanel.Controls[i].AddEquip(EquipName, EquipImage); //THIS DOES NOT WORK
}
}
public UserDsp(System.Windows.Forms.FlowLayoutPanel hostPanel)
{
HostPanel = hostPanel;
}
public void RemoveUser(Int64 UserID)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
HostPanel.Controls.Remove(this[UserID]);
this.List.RemoveAt(i);
}
UsersLogdIn.Remove(UserID);
}
public DisplayControl.UserDisplay this[Int64 UserID]
{
get
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
return (DisplayControl.UserDisplay)this.List[i];
}
}
public List<long> usersLogdIn
{
get
{
return UsersLogdIn;
}
}
}
}
In this code I can create a new PictureBox in the Control's FlowLayoutPanel when instantiating the Control:
newUser.AddEquip(EquipName, EquipImage); //THIS ADDS THE PICTUREBOX CORRECTLY
But when I try to access it through the CollectionBase:
public void AddNewEquip(Int64 UserID, Int64 EquipID, string EquipName, Image EquipImage)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
// Found the Control with UserID
HostPanel.Controls[i].AddEquip(EquipName, EquipImage); //THIS DOES NOT WORK
}
}
I also tried to pull the control out like this:
public void AddNewEquip(Int64 UserID, Int64 EquipID, string EquipName, Image EquipImage)
{
if (this.Count > 0)
{
int i = 0;
while (UserID != Convert.ToInt64(HostPanel.Controls[i].Tag))
{
i++;
}
// Found the Control with UserID
UserDisplay newUserDisplay = HostPanel.Controls[i] as UserDisplay //THIS DOES NOT WORK
}
}
I have looked everywhere for help on this but have not found anything related. Please Help!
Thank you.
I figured it out with some outside help.
Basically I need to typecast the control as UserDisplay. I don't know why it didn't work when I pulled it out using:
UserDisplay newUserDisplay = HostPanel.Controls[i] as UserDisplay
but I used this code instead:
(HostPanel.Controls[i] as UserDisplay).AddEquip(EquipName, EquipImage);
I did make sure that the control was the correct type before I declared it so this way:
if (HostPanel.Controls[i] is UserDisplay)
Thanks for the help.
Let me start off by saying sorry if the title is wrong.
I am being taught Binary Tree Traversal I've been given some of the code, I am really struggling to understand the logic in using the if/else statements and the boolean logic.
I have to traverse the tree using postorder, preorder and inorder methods.
The preorderTraversal method is all ready done and working.
Any suggestions would be appreciated.
The Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BinaryTree
{
class BinaryTree<T>
{
class BinaryTreeNode
{
public BinaryTreeNode Left;
public BinaryTreeNode Right;
public BinaryTreeNode Parent;
public T Data;
public Boolean processed;
public BinaryTreeNode()
{
Left = null;
Right = null;
Parent = null;
processed = false;
}
}
BinaryTreeNode Root;
Comparison<T> CompareFunction;
public BinaryTree(Comparison<T> theCompareFunction)
{
Root = null;
CompareFunction = theCompareFunction;
}
public static int CompareFunction_Int(int left, int right)
{
return left - right;
}
public void preorderTraversal()
{
if (Root != null)
{
BinaryTreeNode currentNode = Root;
Boolean process = true;
int nodesProcessed = 0;
while (nodesProcessed != 11)
{
if (process)
{
Console.Write(currentNode.Data.ToString());
currentNode.processed = true;
nodesProcessed = nodesProcessed +1;
}
process = true;
if (currentNode.Left != null && currentNode.Left.processed == false)
{
currentNode = currentNode.Left;
}
else if (currentNode.Right != null && currentNode.Right.processed ==
false)
{
currentNode = currentNode.Right;
}
else if (currentNode.Parent != null)
{
currentNode = currentNode.Parent;
process = false;
}
}
}
else
{
Console.WriteLine("There is no tree to process");
}
}
public void postorderTraversal()
{
if (Root != null)
{
}
else
{
Console.WriteLine("There is no tree to process");
}
}
public void inorderTraversal()
{
if (Root != null)
{
}
else
{
Console.WriteLine("There is no tree to process");
}
}
public static int CompareFunction_String(string left, string right)
{
return left.CompareTo(right);
}
public void Add(T Value)
{
BinaryTreeNode child = new BinaryTreeNode();
child.Data = Value;
if (Root == null)
{
Root = child;
}
else
{
BinaryTreeNode Iterator = Root;
while (true)
{
int Compare = CompareFunction(Value, Iterator.Data);
if (Compare <= 0)
if (Iterator.Left != null)
{
Iterator = Iterator.Left;
continue;
}
else
{
Iterator.Left = child;
child.Parent = Iterator;
break;
}
if (Compare > 0)
if (Iterator.Right != null)
{
Iterator = Iterator.Right;
continue;
}
else
{
Iterator.Right = child;
child.Parent = Iterator;
break;
}
}
}
}
public bool Find(T Value)
{
BinaryTreeNode Iterator = Root;
while (Iterator != null)
{
int Compare = CompareFunction(Value, Iterator.Data);
if (Compare == 0) return true;
if (Compare < 0)
{
Iterator = Iterator.Left;
continue;
}
Iterator = Iterator.Right;
}
return false;
}
BinaryTreeNode FindMostLeft(BinaryTreeNode start)
{
BinaryTreeNode node = start;
while (true)
{
if (node.Left != null)
{
node = node.Left;
continue;
}
break;
}
return node;
}
public IEnumerator<T> GetEnumerator()
{
return new BinaryTreeEnumerator(this);
}
class BinaryTreeEnumerator : IEnumerator<T>
{
BinaryTreeNode current;
BinaryTree<T> theTree;
public BinaryTreeEnumerator(BinaryTree<T> tree)
{
theTree = tree;
current = null;
}
public bool MoveNext()
{
if (current == null)
current = theTree.FindMostLeft(theTree.Root);
else
{
if (current.Right != null)
current = theTree.FindMostLeft(current.Right);
else
{
T CurrentValue = current.Data;
while (current != null)
{
current = current.Parent;
if (current != null)
{
int Compare = theTree.CompareFunction(current.Data,
CurrentValue);
if (Compare < 0) continue;
}
break;
}
}
}
return (current != null);
}
public T Current
{
get
{
if (current == null)
throw new InvalidOperationException();
return current.Data;
}
}
object System.Collections.IEnumerator.Current
{
get
{
if (current == null)
throw new InvalidOperationException();
return current.Data;
}
}
public void Dispose() { }
public void Reset() { current = null; }
}
}
class TreeTest
{
static BinaryTree<int> Test = new BinaryTree<int>
(BinaryTree<int>.CompareFunction_Int);
static void Main(string[] args)
{
// Build the tree
Test.Add(5);
Test.Add(2);
Test.Add(1);
Test.Add(3);
Test.Add(3); // Duplicates are OK
Test.Add(4);
Test.Add(6);
Test.Add(10);
Test.Add(7);
Test.Add(8);
Test.Add(9);
// Test if we can find values in the tree
for (int Lp = 1; Lp <= 10; Lp++)
Console.WriteLine("Find ({0}) = {1}", Lp, Test.Find(Lp));
// Test if we can find a non-existing value
Console.WriteLine("Find (999) = {0}", Test.Find(999));
// Iterate over all members in the tree -- values are returned in sorted order
foreach (int value in Test)
{
Console.WriteLine("Value: {0}", value);
}
Console.WriteLine("Preorder traversal");
Test.preorderTraversal();
Console.ReadKey();
}
}
}
Use the Recursion, Luke. (Then it's just a matter in what order you visit (and process) the left subtree, right subtree, or the current node itself.)
Here, maybe some nice animations with option to traverse it the way you like, and add and delete so you can have your own example might help: Look at this site
Or maybe CS animation with voice over ... look here.
This is probably a long shot, but I'm trying to minimize the repition in the program I'm working on, and have run into a snag. As can be seen in the ClearTextBoxes() method below, I have a very repetitive bit of code that I would prefer to place inside a foreach loop for succinctness. (Originally the foreach (object box in customBoxes) loop was not there). I tried to do this with the following List, but to no avail. I'm not sure if this is just not possible to do, or if I'm simply doing it wrong. I would appreciate any help you could give, and if this can't be done, then how can I shrink this code block?
Thanks!
List<object> customBoxes = new List<object>();
customBoxes.AddRange(new[] { "TextBox", "DateBox", "DigitBox", "PhoneBox", "WaterTextBox" });
public void ClearTextBoxes()
{
ChildControls ccChildren = new ChildControls();
foreach (object o in ccChildren.GetChildren(rvraDockPanel, 2))
{
foreach (object box in customBoxes)
{
if (o.GetType() == typeof(TextBox))
{
TextBox txt = (TextBox)o;
txt.Text = "";
}
if (o.GetType() == typeof(DigitBox))
{
DigitBox digit = (DigitBox)o;
digit.Text = "";
}
if (o.GetType() == typeof(PhoneBox))
{
PhoneBox phone = (PhoneBox)o;
phone.Text = "";
}
if (o.GetType() == typeof(DateBox))
{
DateBox date = (DateBox)o;
date.Text = "";
}
if (o.GetType() == typeof(WatermarkTextBox))
{
WatermarkTextBox water = (WatermarkTextBox)o;
water.Text = "";
}
}
}
}
List<Type> customBoxes = new List<Type>();
customBoxes.AddRange(new[] { typeof(PhoneBox), typeof(DigitBox), ....." });
foreach (Control c in this.Controls)
{
if (customBoxes.Contains(c.GetType()))
{
c.Text = string.Empty;
}
}
I would create an interface with a ClearText() method.
interface IClearable
{
public void ClearText();
}
Then you can inherit from each control and apply that interface:
class ClearableDigitBox : DigitBox, IClearable
{
public void ClearText() {
Text = String.Empty;
}
}
// etc...
So it's just:
var list = new List<IClearable>;
// ...
foreach (IClearable control in list) control.ClearText();
You could use reflection in some way to mimic some ductyping behavior but i wouldnt go for that solution since it's not performant and ugly.
foreach (object box in customBoxes)
{
var boxType = box.GetType();
var textProperty = boxType.GetProperty("Text");
if (textProperty != null && textProperty.CanWrite)
{
textProperty.SetValue(box, "", null);
}
}
Or you can use dynamic to achieve the same result:
foreach (dynamic box in customBoxes)
{
box.Text = "";
}
The way to go would be to make your custom controls implement a single interface IWithTextProperty which ofcourse exposes the text property.
Aren't all the input boxes a part of Control object?
if so, and you want to clear all the text from the controls
then i would probably have a method like:
public void ClearText(List<Control> items)
{
foreach (Control control in items)
{
control.Text = string.Empty;
}
}
if you just want to locate controls of a specific type
public void ClearText(List<Control> items)
{
foreach (Control control in items)
{
if (control is TextBox)
((TextBox)control).Text = string.Empty;
else if (control is DigitBox)
((DigitBox)control).Text = string.Empty;
else
{ // Handle anything else.}
}
}
In response to a couple of the replies so far, this is the class file I have for the custom boxes. The NumberTextBox class is the default snippet that VS added. I haven't used it, just haven't deleted it either. In addition to the DateBox(which is collapsed to save space) class, there is also a PhoneBox class that inherits from DigitBox as well. the WatermarkTextBox class that DigitBox inherits from is in the WpfToolkit.Extended.dll. The only real difference in these classes is that each adds a method to allow/disallow formatting keys being pressed (parenthesis, periods, hyphens, etc).
This class basically came about as a result of trying to merge several different snippets I found around the web, but the purpose of these boxes is to enable a watermark and also restrict the characters that can be entered into those boxes.
public class NumberTextBox : Control
{
static NumberTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumberTextBox), new FrameworkPropertyMetadata(typeof(NumberTextBox)));
}
}
public class DigitBox : WatermarkTextBox, IClearable
{
#region Constructors
///<summary>
///The default constructor
/// </summary>
public DigitBox()
{
TextChanged += new TextChangedEventHandler(OnTextChanged);
KeyDown += new KeyEventHandler(OnKeyDown);
PreviewKeyDown += new KeyEventHandler(OnPreviewDown);
}
#endregion
#region Properties
new public String Text
{
get { return base.Text; }
set
{
base.Text = LeaveOnlyNumbers(value);
}
}
#endregion
#region Functions
public bool IsNumberKey(Key inKey)
{
if (inKey < Key.D0 || inKey > Key.D9)
{
if (inKey < Key.NumPad0 || inKey > Key.NumPad9)
{
return false;
}
}
return true;
}
public bool IsActionKey(Key inKey)
{
return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return;
}
public string LeaveOnlyNumbers(String inString)
{
String tmp = inString;
foreach (char c in inString.ToCharArray())
{
if (!IsDigit(c))
{
tmp = tmp.Replace(c.ToString(), "");
}
}
return tmp;
}
public bool IsSpaceKey(Key inKey)
{
if (inKey == Key.Space)
{
return true;
}
return false;
}
public bool IsDigit(char c)
{
return (c >= '0' || c <='9');
}
#endregion
#region Event Functions
protected virtual void OnKeyDown(object sender, KeyEventArgs e)
{
e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsSpaceKey(e.Key);
}
protected virtual void OnTextChanged(object sender, TextChangedEventArgs e)
{
base.Text = LeaveOnlyNumbers(Text);
}
protected virtual void OnPreviewDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
e.Handled = true;
}
}
#endregion
}
public class DateBox : DigitBox