child nodes in treeview control automatically checked when parent node checked - asp.net

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);

Related

Asp.net Telerik script issue

I have a line of code which comes inside a Telerik.Web.UI.Webresource.axd file which breaks something in my custom code.
dataBind:function(){if(this._virtualization&&!this._virtualization._isDataBinding&&((this.get_allowPaging()&&this._dataSource.length>this.get_pageSize())||(!this.get_allowPaging()&&this._dataSource.length>this._virtualization._itemsPerView))){this._virtualization._startIndex=null;
this._virtualization.set_bindingType("Client");
this._virtualization.set_cachedData(this._dataSource);
this._virtualization.set_virtualItemCount(this._dataSource.length);
this._virtualization.select();
return;
}
**Array.forEach($telerik.getElementsByClassName(this.get_element().tBodies[0],"rgGroupHeader"),function(i){i.parentNode.removeChild(i)**;
});
I would like to know if it is possible to prevent the below line of code to be executed
Array.forEach($telerik.getElementsByClassName(this.get_element().tBodies[0],"rgGroupHeader"),function(i){i.parentNode.removeChild(i)**;
You can override the dataBind method of RadGrid which will allow you to customize it:
<script>
Telerik.Web.UI.GridClientSideBinding.prototype.dataBind = function () {
// Virtualization
if (this._virtualization && !this._virtualization._isDataBinding &&
((this.get_allowPaging() && this._dataSource.length > this.get_pageSize()) ||
(!this.get_allowPaging() && this._dataSource.length > this._virtualization._itemsPerView))) {
this._virtualization._startIndex = null;
this._virtualization.set_bindingType("Client");
this._virtualization.set_cachedData(this._dataSource);
this._virtualization.set_virtualItemCount(this._dataSource.length);
this._virtualization.select();
return;
}
Array.forEach($telerik.getElementsByClassName(this.get_element().tBodies[0], "rgGroupHeader"), function (element) {
element.parentNode.removeChild(element);
});
Array.forEach($telerik.getElementsByClassName(this.get_element().tBodies[0], "rgFooter"), function (element) {
element.parentNode.removeChild(element);
});
var noRecordsItem = $telerik.getElementByClassName(this.get_element(), "rgNoRecords");
if (noRecordsItem) {
if (this._dataSource.length > 0) {
noRecordsItem.style.display = "none";
} else {
noRecordsItem.style.display = "";
this._setPagerVisibility(this._data.PagerAlwaysVisible);
}
}
var dataItems = this.get_dataItems();
var columns = this.get_columns();
var i, l1, l2;
var tableElement = ($telerik.isOpera) ? this.get_element() : this.get_element().tBodies[0];
if (this._dataSource.length < dataItems.length || tableElement.rows.length == 1) {
for (i = 0, l1 = dataItems.length; i < l1; i++) {
dataItems[i].set_visible(false);
dataItems[i].get_element().style.display = "none";
}
this._cacheDataItems();
}
this._dataBind(this._dataSource);
var firstSelection = true;
// When YahooStyleScrolling is used in RadGrid and user
//scrolls down, select multiple rows using shift + down arrow key,
//the selection is not persisted on next page load
if (this._owner._keyboardNavigationProperties) {
firstSelection = this._owner._keyboardNavigationProperties.firstSelection;
}
var owner = $find(this._owner.get_id());
if (owner._getPositionedDataItems) {
owner._getPositionedDataItems(true);
}
if (this._owner._keyboardNavigationProperties) {
this._owner._keyboardNavigationProperties.firstSelection = firstSelection;
}
this._fixRowsClassNames();
this._owner.raise_dataBound(Sys.EventArgs.Empty);
for (i = 0, l2 = columns.length; i < l2; i++) {
var isVisible = false;
if (columns[i].get_element().style.visibility != "hidden" && (columns[i].Display == null || columns[i].Display == true) &&
(columns[i]._data.Display == null || columns[i]._data.Display)) {
isVisible = true;
}
if (!isVisible) {
this.hideColumn(i);
}
}
if (this.get_id() == this._owner._masterClientID) {
var grid = $find(this._owner.get_id());
if (grid._scrolling) {
this._owner._scrolling.setHeaderAndFooterDivsWidth();
grid._scrolling._initializeVirtualScrollPaging(true);
}
}
}
</script>

Custom control that's not shown

I'm porting a v2 to v3 app map and there's one thing I can't get to work.
I have a custom control that is not shown, anything.
I'm not sure where is the problem so I'll post everything i think is relevant, ask for some more if needed
Here's the constructor:
Note that there's still the comments from v2
function Semaforo(){}
//Semaforo.prototype = new GControl();
Semaforo.prototype.semaforo = document.createElement("img");
Semaforo.prototype.initialize = function(map) {
var container = document.createElement("div");
var semaforoDiv = document.createElement("img");
semaforoDiv.setAttribute("class", "semaforo");
this.setButtonStyle_(semaforoDiv);
this.semaforo = semaforoDiv;
container.appendChild(semaforoDiv);
semaforoDiv.setAttribute("src", "img/semaforo_rojo.png");
map.getContainer().appendChild(container);
return container;
}
And some of the methods:
Semaforo.prototype.setColor = function(color, mapa) {
this.semaforo.setAttribute("src", "img/semaforo_" + color + ".png");
if(color == "rojo")
{
this.semaforo.setAttribute("alt", "Tr�fico dif�cil");
this.semaforo.setAttribute("title", "Tr�fico dif�cil");
}
else if(color == "ambar")
{
this.semaforo.setAttribute("alt", "Tr�fico irregular");
this.semaforo.setAttribute("title", "Tr�fico irregular");
}
else
{
this.semaforo.setAttribute("alt", "Tr�fico fluido");
this.semaforo.setAttribute("title", "Tr�fico fluido");
}
}
Semaforo.prototype.getDefaultPosition = function() {
return new google.maps.ControlPosition.TOP_RIGHT;
//return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(0, 0)); //TO DO
}
Semaforo.prototype.setButtonStyle_ = function(button) {
button.style.width = "19px";
button.style.height = "53px";
button.style.cursor = "default";
}
function getIconoSemaforo(color, mapa){
var semaforo = new Semaforo();
semaforo.setColor(color, mapa);
return semaforo;
}
Here is where I call the constructor and try to make/show the control
function incluirDatosXML()
{
for (var i=0; i<ciudadDato.length; i++)
{
if (i==0)
{
if (semaforoDato[i]!="no")
{
var semaforo = new Semaforo(this.semaforo, map[1]);
map[1].controls[google.maps.ControlPosition.TOP_RIGHT].push(this.semaforo);
//map[1].addControl(semaforo);
semaforo.setColor(semaforoDato[i], map[1]);
/*google.maps.event.addListener(map[1], 'idle', function() {
map[1].controls[google.maps.ControlPosition.TOP_RIGHT].push(this.semaforo);
});*/
}
}
if (i==1)
{
if (semaforoDato[i]!="no")
{
var semaforo = new Semaforo(this.semaforo, map[2]);
//map[2].addControl(semaforo);
semaforo.setColor(semaforoDato[i], map[2]);
//map[2].controls[google.maps.ControlPoistion.TOP_RIGHT].push(this.semaforo);
}
}
if (i==2)
{
if (semaforoDato[i]!="no")
{
var semaforo = new Semaforo(this.semaforo, map[3]);
//map[3].addControl(semaforo);
semaforo.setColor(semaforoDato[i], map[3]);
//map[3].controls[google.maps.ControlPoistion.TOP_RIGHT].push(this.semaforo);
}
}
$("#clima"+(i+1)).attr("class",climaDato[i]+"_mini");
$("#temp"+(i+1)).html(temperaturadDato[i]+"°");
}
}
So all you can see there is what i tested so far even there's still some comments from previous testings

get sibling controls

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;
}

In AS3/Flex, how can I get from flat data to hierarchical data?

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;
}

Flex: Updating a Tree control

I've a tree control with checkboxes that uses the control from http://www.sephiroth.it/file_detail.php?id=151#
Somehow I can't get the control to update when I change the dataProvider (i.e. by clicking a checkbox) the only way I can get it to update is to use the scrollbar. How do I force the update? I've tried all possible methods I can figure out? (see update below)
Also how can I reset the Tree (collpasing all nodes, scroll to the top in a large tree)?
package offerta.monkeywrench.components
{
import offerta.monkeywrench.components.componentClasses.TreeCheckBoxItemRenderer;
import mx.collections.ArrayCollection;
import mx.events.TreeEvent;
public class WatchTree extends TreeCheckBox
{
public var idProperty:String;
public var watchFactory:Function;
private var _wSet:Boolean = false;
/* clientId: */
private var _clientId:String;
[Bindable]
public function get clientId():String
{
return _clientId;
}
public function set clientId(value:String):void
{
this._clientId = value;
}
/* //clientId */
/* watching: */
private var _watching:ArrayCollection;
[Bindable]
public function set watching(value:ArrayCollection):void
{
this._watching = value;
}
public function get watching():ArrayCollection
{
return this._watching;
}
/* //watching */
override public function initialize() :void
{
super.initialize();
addEventListener("itemCheck", onItemCheck, false, 0, true);
}
private function isWatching(id:String):Boolean
{
for each(var w:Object in this._watching)
{
if(w[this.idProperty]==id) return true;
}
return false;
}
private function onItemCheck(event:TreeEvent):void
{
var item:Object = event.item as Object;
var currentValue:uint = (event.itemRenderer as TreeCheckBoxItemRenderer).checkBox.checkState;
if(item.children==null)
{
currentValue==2 ? addWatch(item.Id) : removeWatch(item.Id);
}
else
{
for each(var x:Object in item.children)
{
currentValue==2 ? addWatch(x.Id) : removeWatch(x.Id);
}
}
updateParents(item, currentValue);
updateChilds(item, currentValue);
this.dataProvider.refresh();
super.invalidateProperties();
super.invalidateDisplayList();
super.updateDisplayList(this.unscaledWidth, this.unscaledHeight);
}
private function updateParents(item:Object, value:uint):void
{
var checkValue:String = (value == ( 1 << 1 | 2 << 1 ) ? "2" : value == ( 1 << 1 ) ? "1" : "0");
var parentNode:Object = item.parent;
if(parentNode)
{
for each(var x:Object in parentNode.children)
{
if(x.checked != checkValue)
{
checkValue = "2"
}
}
parentNode.checked = checkValue;
updateParents(parentNode, value);
}
}
private function updateChilds(item:Object, value:uint):void
{
var middle:Boolean = (value&2<<1)==(2<<1);
if(item.children!=null && item.children.length>0&&!middle)
{
for each(var x:Object in item.children)
{
x.checked = value == (1<<1|2<<1) ? "2" : value==(1<<1) ? "1" : "0";
updateChilds(x, value);
}
}
}
private function addWatch(id:String):void
{
if(isWatching(id)) return;
this._watching.addItem(this.watchFactory(id, this.clientId));
}
private function removeWatch(id:String):void
{
for(var i:int=0, n:int=this._watching.length; i<n; ++i)
{
if(this._watching[i][this.idProperty]==id)
{
this._watching.removeItemAt(i);
return;
}
}
}
public function update(__watching:ArrayCollection, __clientId:String):void
{
clientId = __clientId;
watching = __watching;
if(this.dataProvider!=null)
{
var ws:ArrayCollection = ArrayCollection(this.dataProvider);
for each(var group:Object in ws)
{
var count:int = 0;
for each(var child:Object in group.children)
{
if(isWatching(child.Id))
{
child.checked = "1";
count++;
}
}
group.checked = (count==0 ? "0" : (count==group.children.length ? "1" : "2"));
}
this._wSet = false;
var dp:ArrayCollection = ArrayCollection(this.dataProvider);
dp.refresh();
super.invalidateProperties();
super.invalidateDisplayList();
super.updateDisplayList(this.unscaledWidth, this.unscaledHeight);
//scroll up the list???
//collapse? (doesn't work)
this.expandItem(null, false);
}
}
}
}
I've found the Tree control a little touchy in Flex. The way I ended up forcing a redraw was to disconnect the dataProvider and reconnect it, then force validation, something a bit like this :
private function forceRedraw(tree:Tree, dataProvider:Object):void
{
var scrollPosition:Number = tree.verticalScrollPosition;
var openItems:Object = tree.openItems;
tree.dataProvider = dataProvider;
tree.openItems = openItems;
tree.validateNow();
tree.verticalScrollPosition = scrollPosition;
}
I guess this incidentally answers the second part of your question since all you'd have to do is null out the openItems collection and set the verticalScrollPosition to 0.
You might have another problem: whenever you check an item the tree scrolls to the top and this is just annoying. To solve this problem you should update the TreeCheckBox.as file this way:
in function checkHandler:
private function checkHandler( event: TreeEvent ): void;
comment the commitProperties(); call.
Now it should work well.
Cheers.
I've had some minor problem with this solution, var scrollPosition:Number = tree.verticalScrollPosition; is constantly 0??

Resources