In my Program there's is a user right, I'm taking those rights from the user rights that I have saved in the SQL database to the static variables when user login to the system, I want to restrict user from clicking not allowed TreeNodes. So It's checking from the static variable values. In my Form Load, I wrote:
if (bl_Static.AddReq != true)
{
treeView1.Nodes.RemoveAt(6);
}
But It's not working. Can you help me with this, please?
I think you are calling the RemoveAt method of the wrong parent node so the target node
won't be removed if it is not in the TreeNodeCollection of treeView1.Nodes.
To solve the problem, find the target node by it's unique key/name using the TreeNodeCollection.Find method and check whether it is a root or child node to call the Remove method of the right collection:
if (!bl_Static.AddReq)
{
var tarNode = treeView1.Nodes.Find("GetTheNameFromTheDesigner", true).FirstOrDefault();
if(tarNode != null)
{
if (tarNode.Parent != null)
tarNode.Parent.Nodes.Remove(tarNode);
else
treeView1.Nodes.Remove(tarNode);
}
}
Related
Edit: I am not looking for an implementation but just for some keywords to search and methodologies to get me started.
I am struggling with generating a dependency tree where child nodes are updated by an external process and the requirement is to update all parent nodes of updated child nodes.
Example: Imagine a tree such as this: O [parent], O(l) [left child], O(r) [right child], O(ll), O(lr), O(rl), and O(rr). O(ll), O(lr), O(rl), and O(rr) have reference to a data collection that is updated at random intervals).
I want to implement a pull process, where at certain intervals a process checks whether O is updated. "Updated" is defined as being updated when all child nodes are updated, else just the cached value(result) of that node is used. The pull process's job is to ensure that O is updated when any of the child nodes is not updated. This means that the process needs to traverse the tree and check whether O(ll), O(lr), O(rl), and O(rr) are updated. If the data collection, those child nodes reference, are updated since the last update of those child nodes then those child nodes need to be updated as function of the changed data collection. If the data collection is updated and hence the child nodes O(ll), O(lr), O(rl), and O(rr) are updated as well and this means that O(l) and O(r) also need to be updated and subsequently O will also be updated. Each child node is input to its parent node.
The complexity here is that each child node is shared among different trees, meaning, a child node of one tree can also be any child node of another tree. The purpose of this structure is to avoid the re-calculation of a child node when it is already up-to-date. The child nodes are shared if different trees implement a child node with the exact same functionality (function and parameterization) as the already existing child node.
I am stuck with the design of this structure and how to go about implementing it. I have not provided code yet because I am stuck with the design thought process. Essentially each child is function and depends on dependent functions itself.
What makes me wonder is whether C# offers the ability to decorate methods and classes in order to simplify the checking of whether a node is updated or not. Also does lazy evaluation play a role in this process at all?
I suggest defining a class that keeps track whether its children have been updated via a flag, e.g. a Boolean named Dirty. A node in the tree can tell its parents to become dirty by raising an event. When a node returns its own value, it should check the flag and recompute its own value only when needed. When recomputing, it should check the Value of each child, each of which will then check its own dirty flag, and so on, recursively.
class Node<T>
{
event EventHandler Changed;
private T _value;
private bool _dirty = true;
private List<Node<T>> _children = new List<Node<T>>();
public void AddChild(Node<T> child)
{
child.Changed += (s,e) => _dirty = true;
_children.Add(child);
}
protected void OnChanged()
{
if (Changed != null) Changed(this, new EventArgs());
}
public T Value
{
get
{
if (_dirty)
{
this.Value = ComputeValueFromChildren();
_dirty = false;
}
return _value;
}
set
{
_value = value;
OnChanged();
}
}
private T ComputeValueFromChildren()
{
var values = _children.Select( child => child.Value );
//Return the new value based on the children
}
}
I want to dispose a specific type of User control from panel. Right now i am using foreach loop to dispose the User control.
foreach (CTRL.box bx in RightPanel.Controls.OfType<CTRL.box>())
{
bx.Dispose();
}
But it is not working properly. while checking in google i find the below code.
while(tabControlToClear.Controls.Count > 0)
{
var tabPage = tabControlToClear.Controls[0];
tabControlToClear.Controls.RemoveAt(0);
tabPage.Dispose();
// Clear out events.
foreach (EventHandler subscriber in tabPage.Click.GetInvocationList())
{
tabPage.Click -= subscriber;
}
}
I am trying to do this, But for me it is a specific User control i need to dispose. they are other User controls which should be required in my form. Overall i want to dispose box User control from my form.
while (RightPanel.Controls.OfType<CTRL.box>().Count() > 0)
{
var panel = RightPanel.Controls.OfType<CTRL.box>()[0];//Here i am getting error "Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<Project_Server.CTRL.box>'"
}
Can anyone help me to fix this error.
Error is pretty clear, you cannot apply indexing on IEnumerable
I would suggest use First or FirstOrDefault extension method to retrieve first element and delete it.
var panel = RightPanel.Controls.OfType<CTRL.box>().FirstOrDefault();
if(panel != null)
{
//logic
}
In case, if you would like to remove all controls of type CTRL.box use this.
List<Control> controls= RightPanel.Controls.OfType<CTRL.box>().ToList();
foreach(Control c in controls)
{
RightPanel.Controls.Remove(c);
c.Dispose();
}
I have a question concerning TreeViews and their Nodes in C#.
What I currently try to do. I have a TreeView and next to it a TableLayoutPanel. When I click of the Nodes, I want to call a specific Method and display the Data
in the TableLayoutPanel. Displaying the data works fine, but my problem is that I dont know exactly how to determine what Node/ChildNode has been selected.
I have a TreeView that looks like this
Root1
R1Child1
R1Child2
Root2
R2Child1
R2Child2
Root3
R3Child1
R3Child2
I currently handle this by an AfterSelect Method and just check the selected Node for the Text.
private void treeHardware_AfterSelect(object sender, TreeViewEventArgs e)
{
if (e.Node.Text == SysInfo.CPU.Name)
{
deleteRows();
initFixedRows();
updateTableCPU();
}
else if (e.Node.Text == ramNameIdent)
{
deleteRows();
initFixedRows();
updateTableRAM(e.Node.Index);
}
else if (e.Node.Text == "Memory")
{
deleteRows();
initFixedRows();
loadRAMDetails(0);
loadRAMOverview();
}
else if( e.Node.Text == "Mainboard")
{
deleteRows();
initFixedRows();
updateTableMainboard();
}
else
{
Console.WriteLine("ERROR");
}
}
In my Opinion this is a very unpractical way to check what Node has been clicked, because it just checks Strings, and it isnt very effective..
Next Problem, for Memory Node. I display all installed Physical Memories and add each of them as a ChildNode. Now when I click one of them, it should display the Data of the selected Memory in my TableLayoutPanel. But It always just shows the "last" one.
Hope hat you understand what I mean...
If not, just ask for more Information :-)
Cheers,
Consti
Use the Tag Property , put an ID in the tag property that is unique for every node
I'm developing an ASP.NET 4.0 web application and I am using a TreeView control. I have one problem that I really can't understand why this is happening. I have checkboxes associated with the tree items.
If the checkbox is not checked everything works just fine, but when I execute the following line:
node.ChildNodes.Clear();
If the checkbox is checked for the node, the node.Parent is null after the Clear(). If it is not checked, parent is still correct. I really can't understand why the clearing of the childnodes collection will also clear my parent reference. I actually don't use or modify the checked property within this call. I am also 100% sure that my parent isn't a child to my node as well (why would it differ if it checked or not).
The workaround I need to use in order for the code to work as expected is:
TreeNode[] checkedNodes = new TreeNode[tvResults.CheckedNodes.Count];
tvResults.CheckedNodes.CopyTo(checkedNodes, 0);
foreach (TreeNode checkedNode in checkedNodes) // Uncheck all nodes temporary.
checkedNode.Checked = false;
node.ChildNodes.Clear(); // Now it is ok to clear and parent is "saved".
foreach (TreeNode checkedNode in checkedNodes) // Recheck all checked nodes again.
checkedNode.Checked = true;
Any idea anyone about this issue?
Thanks,
Mattias
PS! Please be kind, this is my first question ever...
Below is the code from ASP.NET TreeNodeCollection.Clear (from .NET 4.5). As you can see, it does clear all checked nodes without performing any validation. So this is by design (rather a bug by design) and not a bug in your code. My advice would be add an extension method that performs the workaround you listed in the question so that you can easily reuse it.
// System.Web.UI.WebControls.TreeNodeCollection
/// <summary>Empties the <see cref="T:System.Web.UI.WebControls.TreeNodeCollection" /> object.</summary>
public void Clear()
{
if (this.Count == 0)
{
return;
}
if (this._owner != null)
{
TreeView owner = this._owner.Owner;
if (owner != null)
{
if (owner.CheckedNodes.Count != 0)
{
owner.CheckedNodes.Clear();
}
for (TreeNode treeNode = owner.SelectedNode; treeNode != null; treeNode = treeNode.Parent)
{
if (this.Contains(treeNode))
{
owner.SetSelectedNode(null);
break;
}
}
}
}
foreach (TreeNode current in this._list)
{
current.SetParent(null);
}
this._list.Clear();
this._version++;
if (this._isTrackingViewState)
{
this.Log.Clear();
}
this.Log.Add(new TreeNodeCollection.LogItem(TreeNodeCollection.LogItemType.Clear, 0, this._isTrackingViewState));
}
What we have
We have some complex winforms control. To store its state we use some custom serialized class. Lets say we've serialized it to xml. Now we could save this xml as a file in User directory or to include it in some another file....
But...
The question is,
if user creates several such controls across his winform application (at design time), what unique identifier is better to use in order to know which of the saved configs belongs to which of these controls?
So this identifier should:
Stay the same across application launches
Automatic given (or already given, like we can assume that Control.Name is always there)
Unique across application
I think one could imagine several ways of doing it and I believe there are might be some default ways of doing it.
What is better to use? Why?
This small extension method does the work:
public static class FormGetUniqueNameExtention
{
public static string GetFullName(this Control control)
{
if(control.Parent == null) return control.Name;
return control.Parent.GetFullName() + "." + control.Name;
}
}
It returns something like 'Form1._flowLayoutPanel.label1'
Usage:
Control aaa;
Dictionary<string, ControlConfigs> configs;
...
configs[aaa.GetFullName()] = uniqueAaaConfig;
I've been using a compound indentifier made of a full tree of control hierarchy. Assuming that your form name is Form1, then you have a groupbox Groupbox1 and a textbox TextBox1, the compound identifier would be Form1/Groupbox1/TextBox1.
If you'd like to follow this, here are the details:
http://netpl.blogspot.com/2007/07/context-help-made-easy-revisited.html
This is the method I've ended up creating to define a unique name that includes the full name of the form (with it's namespace) then each parent control above the control in question. So it could end up being something like:
MyCompany.Inventory.SomeForm1.SomeUserControl1.SomeGroupBox1.someTextBox1
static string GetUniqueName(Control c)
{
StringBuilder UniqueName = new StringBuilder();
UniqueName.Append(c.Name);
Form OwnerForm = c.FindForm();
//Start with the controls immediate parent;
Control Parent = c.Parent;
while (Parent != null)
{
if (Parent != OwnerForm)
{
//Insert the parent control name to the beginning of the unique name
UniqueName.Insert(0, Parent.Name + ".");
}
else
{
//Insert the form name along with it's namespace to the beginning of the unique name
UniqueName.Insert(0, OwnerForm.GetType() + ".");
}
//Advance to the next parent level.
Parent = Parent.Parent;
}
return UniqueName.ToString();
}