Is there some way to find sibling controls / or sibling activity?
In ASP.NET I found a solution by user md1337 solution's, but for WF4 I can't find it.
Thanks a lot.
public static IEnumerable<T> FindVisualChildren<T>(System.Windows.DependencyObject depObj) where T : System.Windows.DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
System.Windows.DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
And in mi Create Activity method I do:
foreach (TextBlock tb in RulesDll.ObjectsClass.FindControls.FindVisualChildren<TextBlock>(target))
{
string a = tb.Text;
}
Related
i am working on an application in asp.net.I have used a treeview to show Category.After storing the checked node value into database i want to uncheck all the treeview nodes. for this i have the following code:
foreach (TreeNode node in TreeView1.CheckedNodes)
{
node.Checked=false;
}
but it is showing error:
Collection was modified; enumeration operation may not execute
please help me.
thanks!
foreach is read only and you can't change collection into foreach.
you must use for loop:
for (int i = 0; i < TreeView1.Nodes.Count; i++)
{
TreeView1.Nodes[i].Checked = false;
}
//foreach (TreeNode node in TreeView1.CheckedNodes)
for(int i=0; i<TreeView1.CheckedNodes.Count; i++)
{
TreeNode node = TreeView1.CheckedNodes[i];
node.Checked = false;
}
The CheckedNodes.Count variable is re-evaluated on each pass. So just keep clearing the check box at the 0 index.
int tvCT;
tvCT = TreeView1.CheckedNodes.Count;
if (tvCT > 0)
{
for (int i = 0; i < tvCT; i++)
{
TreeNode node = TreeView1.CheckedNodes[0];
node.Checked = false;
}
}
while (TreeView1.CheckedNodes.Count > 0)
{
TreeView1.CheckedNodes[0].Checked = false;
}
This is a pretty simple block that works for me.
foreach (TreeNode node in TreeView1.Nodes)
{
node.Checked = false;
foreach (TreeNode item1 in node.ChildNodes)
{
item1.Checked = false;
foreach (TreeNode item2 in item1.ChildNodes)
{
item2.Checked = false;
}
}
}
Check it.....! it's work
I'm using TreeView control. Binding values from database with check box.
Nearly three children are there for parent node like
Parent1
child1
child2
child3
Parent2
child1
child2
child3
I can able to bind data which is from 3 tables all are working well. I want a facility when a parent node checks all its corresponding child automatically get checked.If I click on parent 1 ,child 123 get checked. If I check child1, child2 and child3 get checked. If I check child 2 all child 3 items get checked. How to do that?
Thanks in Advance
Amrutha
The javascript function below can be used to check all child nodes if the parent is checked and check parent node if at least one child node is checked otherwise it is unchecked:
function OnTreeClick(evt) {
var src = window.event != window.undefined ? window.event.srcElement : evt.target;
var isChkBoxClick = (src.tagName.toLowerCase() == "input" && src.type == "checkbox");
var t = GetParentByTagName("table", src);
if (isChkBoxClick) {
var parentTable = GetParentByTagName("table", src);
var nxtSibling = parentTable.nextSibling;
if (nxtSibling && nxtSibling.nodeType == 1) {
if (nxtSibling.tagName.toLowerCase() == "div") {
CheckUncheckChildren(parentTable.nextSibling, src.checked);
}
}
CheckUncheckParents(src, src.checked);
}
}
function CheckUncheckChildren(childContainer, check) {
var childChkBoxes = childContainer.getElementsByTagName("input");
var childChkBoxCount = childChkBoxes.length;
for (var i = 0; i < childChkBoxCount; i++) {
childChkBoxes[i].checked = check;
}
}
function CheckUncheckParents(srcChild, check) {
var parentDiv = GetParentByTagName("div", srcChild);
var parentNodeTable = parentDiv.previousSibling;
if (parentNodeTable) {
var checkUncheckSwitch;
var isAllSiblingsChecked = AreAllSiblingsChecked(srcChild);
if (isAllSiblingsChecked) {
checkUncheckSwitch = true;
}
else {
checkUncheckSwitch = false;
}
var inpElemsInParentTable = parentNodeTable.getElementsByTagName("input");
if (inpElemsInParentTable.length > 0) {
var parentNodeChkBox = inpElemsInParentTable[0];
parentNodeChkBox.checked = checkUncheckSwitch;
CheckUncheckParents(parentNodeChkBox, checkUncheckSwitch);
}
}
}
function AreAllSiblingsChecked(chkBox) {
var parentDiv = GetParentByTagName("div", chkBox);
var childCount = parentDiv.childNodes.length;
var k = 0;
for (var i = 0; i < childCount; i++) {
if (parentDiv.childNodes[i].nodeType == 1) {
if (parentDiv.childNodes[i].tagName.toLowerCase() == "table") {
var prevChkBox = parentDiv.childNodes[i].getElementsByTagName("input")[0];
//if any of sibling nodes are not checked, return false
if (prevChkBox.checked) {
//add each selected node one value
k = k + 1;
}
}
}
}
//Finally check any one of child node is select if selected yes then return ture parent node check
if (k > 0) {
return true;
}
else {
return false;
}
}
function GetParentByTagName(parentTagName, childElementObj) {
var parent = childElementObj.parentNode;
while (parent.tagName.toLowerCase() != parentTagName.toLowerCase()) {
parent = parent.parentNode;
}
return parent;
}
I used this javascript to solve my problem.
A simple recursive function could do that.
private bool checkTreeNodes(TreeNodeCollection nodes, bool parentChecked)
{
var isChecked = parentChecked;
foreach (TreeNode node in nodes)
{
if (node.Checked || parentChecked)
{
checkTreeNodes(node.Nodes, true);
node.Checked = true;
isChecked = true;
}
else
{
node.Checked = checkTreeNodes(node.Nodes, false);
isChecked = isChecked || node.Checked;
}
}
return isChecked;
}
use it like:
checkTreeNodes(myTree.Nodes, false);
I have 45 dropdown lists in my asp page. There are some methods that I can apply to all of these dropdowns. Is it possible to convert them into an array of dropdowns for ease of use?
I would use recursion to look for all dropdowns on your page. Based on this post it would be something like:
public static List<T> FindControls<T>(System.Web.UI.ControlCollection Controls) where T : class
{
List<T> found = new List<T>();
FindControls<T>(Controls, found);
return found;
}
private static void FindControls<T>(System.Web.UI.ControlCollection Controls, List<T> found) where T : class
{
if (Controls != null && Controls.Count > 0)
{
for (int i = 0; i < Controls.Count; i++)
{
if (Controls[i] is T)
{
found.add(Controls[i] as T);
}
else
FindControl<T>(Controls[i].Controls, found);
}
}
}
Once you have your list of dropdowns you can apply whatever methods you see fit.
Using Linq to Objects, an Extension method and Generics we can make this very concise thus:
Method Call to Get all DropDowns
var DropDowns = FindAllControlsByType<DropDownList>(MyBaseControlArray);
Find Controls Method
public static IEnumerable<Control> FindAllControlsByType<T>(IEnumerable<Control> MyCollection) where T : class
{
return MyCollection.Cast<Control>().Descendants(d => d.Controls.Cast<Control>()).Where(l => l.GetType().Equals(typeof(T)));
}
Descendants Extension Method
static public class LinqExtensions
{
static public IEnumerable<T> Descendants<T>(this IEnumerable<T> source,
Func<T, IEnumerable<T>> DescendBy)
{
foreach (T value in source)
{
yield return value;
foreach (T child in DescendBy(value).Descendants<T>(DescendBy))
{
yield return child;
}
}
}
}
EDIT
I've been looking at making this all a mite more generic so here is a completely generic solution that will traverse an object graph from a specified start point extracting all elements of the given type.
public static class Utils
{
public static IEnumerable<IEnumerable<T>> GetCollections<T>(object obj)
{
if (obj == null) throw new ArgumentNullException("obj");
var type = obj.GetType();
var res = new List<IEnumerable<T>>();
foreach (var prop in type.GetProperties())
{
// is IEnumerable<T>?
if (typeof(IEnumerable<T>).IsAssignableFrom(prop.PropertyType))
{
var get = prop.GetGetMethod();
if (!get.IsStatic && get.GetParameters().Length == 0) // skip indexed & static
{
var collection = (IEnumerable<T>)get.Invoke(obj, null);
if (collection != null) res.Add(collection);
}
}
}
return res;
}
public static IEnumerable<V> FindAllControlsByType<V, T>(V MyCollection) where T : class
{
return Utils.GetCollections<V>(MyCollection).Descendants(d => d).Where(l => typeof(T).IsAssignableFrom(l.GetType()));
}
}
static public class LinqExtensions
{
static public IEnumerable<T> Descendants<T>(this IEnumerable<IEnumerable<T>> source,
Func<IEnumerable<IEnumerable<T>>, IEnumerable<IEnumerable<T>>> DescendBy)
{
foreach (IEnumerable<T> collection in source)
{
foreach (T value in collection)
{
yield return value;
foreach (T child in DescendBy(Utils.GetCollections<T>(value)).Descendants<T>(DescendBy))
{
yield return child;
}
}
}
}
}
And we can call that using:
var DropDowns = Utils.FindAllControlsByType<Control, DropDownList>(BaseControl);
Basically the two types are the base class and the specific child class that you want to extract. You'll notice that the process identifies all collections of the base class that are contained within each instance of the base class. This means we're not tied to Controls as the collection and could use this within other structures. Any additional optimisations welcomed.
I have some data that gets pulled out of a database and mapped to an arraycollection. This data has a field called parentid, and I would like to map the data into a new arraycollection with hierarchical information to then feed to an advanced data grid.
I think I'm basically trying to take the parent object, add a new property/field/variable of type ArrayCollection called children and then remove the child object from the original list and clone it into the children array? Any help would be greatly appreciated, and I apologize ahead of time for this code:
private function PutChildrenWithParents(accountData : ArrayCollection) : ArrayCollection{
var pos_inner:int = 0;
var pos_outer:int = 0;
while(pos_outer < accountData.length){
if (accountData[pos_outer].ParentId != null){
pos_inner = 0;
while(pos_inner < accountData.length){
if (accountData[pos_inner].Id == accountData[pos_outer].ParentId){
accountData.addItemAt(
accountData[pos_inner] + {children:new ArrayCollection(accountData[pos_outer])},
pos_inner
);
accountData.removeItemAt(pos_outer);
accountData.removeItemAt(pos_inner+1);
}
pos_inner++;
}
}
pos_outer++;
}
return accountData;
}
I had a similar problem with a hierarchical task set which was slightly different as it has many root elements, this is what i did, seems good to me:
public static function convertFlatTasks(tasks:Array):Array
{
var rootItems:Array = [];
var task:TaskData;
// hashify tasks on id and clear all pre existing children
var taskIdHash:Array = [];
for each (task in tasks){
taskIdHash[task.id] = task;
task.children = [];
task.originalChildren = [];
}
// loop through all tasks and push items into their parent
for each (task in tasks){
var parent:TaskData = taskIdHash[task.parentId];
// if no parent then root element, i.e push into the return Array
if (parent == null){
rootItems.push(task);
}
// if has parent push into children and originalChildren
else {
parent.children.push(task);
parent.originalChildren.push(task);
}
}
return rootItems;
}
Try this:
AccountData:
public class AccountData
{
public var Id:int;
public var ParentId:int;
public var children:/*AccountData*/Array;
public function AccountData(id:int, parentId:int)
{
children = [];
this.Id = id;
this.ParentId = parentId;
}
}
Code:
private function PutChildrenWithParents(accountData:ArrayCollection):AccountData
{
// dummy data for testing
//var arr:/*AccountData*/Array = [new AccountData(2, 1),
// new AccountData(1, 0), // root
// new AccountData(4, 2),
// new AccountData(3, 1)
// ];
var arr:/*AccountData*/Array = accountData.source;
var dict:Object = { };
var i:int;
// generate a lookup dictionary
for (i = 0; i < arr.length; i++)
{
dict[arr[i].Id] = arr[i];
}
// root element
dict[0] = new AccountData(0, 0);
// generate the tree
for (i = 0; i < arr.length; i++)
{
dict[arr[i].ParentId].children.push(arr[i]);
}
return dict[0];
}
dict[0] holds now your root element.
Maybe it's doesn't have the best possible performance but it does what you want.
PS: This code supposes that there are no invalid ParentId's.
Here's what I ended up doing, apparently you can dynamically add new properties to an object with
object['new_prop'] = whatever
From there, I used a recursive function to iterate through any children so you could have n levels of the hierarchy and if it found anything it would pass up through the chain by reference until the original function found it and acted on it.
private function PutChildrenWithParents(accountData : ArrayCollection) : ArrayCollection{
var pos_inner:int = 0;
var pos_outer:int = 0;
var result:Object = new Object();
while(pos_outer < accountData.length){
if (accountData[pos_outer].ParentId != null){
pos_inner = 0;
while(pos_inner < accountData.length){
result = CheckForParent(accountData[pos_inner],
accountData[pos_outer].ParentId);
if ( result != null ){
if(result.hasOwnProperty('children') == false){
result['children'] = new ArrayCollection();
}
result.children.addItem(accountData[pos_outer]);
accountData.removeItemAt(pos_outer);
pos_inner--;
}
pos_inner++;
}
}
pos_outer++;
}
return accountData;
}
private function CheckForParent(suspectedParent:Object, parentId:String) : Object{
var parentObj:Object;
var counter:int = 0;
if ( suspectedParent.hasOwnProperty('children') == true ){
while (counter < suspectedParent.children.length){
parentObj = CheckForParent(suspectedParent.children[counter], parentId);
if (parentObj != null){
return parentObj;
}
counter++;
}
}
if ( suspectedParent.Id == parentId ){
return suspectedParent;
}
return null;
}
When I use PropertyInfo.SetValue in asp.net , it throws a stackoverflow exception.
That I write this code:
for (int i = 0; i < rivalSeriesIDList.Count; i++)
{
cardb_series rivalSeries = seriesBll.GetSeriesInfoByID(rivalSeriesIDList[i].ToString());
this.GetType().GetProperty("brandid" + (i + 1)).SetValue(this, rivalSeries.brand_id, null);
this.GetType().GetProperty("seriesid" + (i + 1)).SetValue(this, rivalSeries.series_id, null);
}
And brandid+number and seriesid+number is a property of aspx_page. like this:
public int brandid1
{
get
{
if (Request.Form["brandid1"] != null)
return int.Parse(Request.Form["brandid1"]);
if (Request["brandid1"] != null)
return int.Parse(Request["brandid1"]);
return 0;
}
set
{
brandid1 = value;
}
}
when I test the code in a Console Application ,It is all right . But when I test it in a Web Application ,it will cause a stack overflow exception .
I don't know why. Because of web is no-state?
Thanks.
cause you call your property recursively, and will get the same exception even if you will call the property directly
public int brandid1 <- this one
{
get
{
if (Request.Form["brandid1"] != null)
return int.Parse(Request.Form["brandid1"]);
if (Request["brandid1"] != null)
return int.Parse(Request["brandid1"]);
return 0;
}
set
{
and this one -> brandid1 = value;
}
}
I don't know what do you want to do, but try this
private int _brandid1;
public int brandid1 <- this one
{
get
{
if (Request.Form["brandid1"] != null)
return int.Parse(Request.Form["brandid1"]);
if (Request["brandid1"] != null)
return int.Parse(Request["brandid1"]);
return 0;
}
set
{
_brandid1 = value;
}
}