Solved

save selected child node

Posted on 2011-09-04
41
538 Views
Last Modified: 2013-12-17
Hi

Does anyone know how to save a selected child node in a C# silverlight treeview?

The treeview comes in 2 languages which is controlled by a combobox to select the preferred language, when i have the english language chosen i select my child node but when i change to portuguese it needs to keep that child node selected.

snippet..
private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            var selectedItem = (UserRoleTreeData.Level)e.NewValue;
            if (selectedItem != null)
            {
                foreach (UserRoleTreeData.Level item in treeView1.Items)
                {
                    #region General User Tools
                    if (item.Name.Equals("General User Tools") || item.Name.Equals("Geral Usuário Ferramentas"))
                    {
                        foreach (UserRoleTreeData.Level items in item.Children)
                        {
                            if (items != null)
                            {
                                if (selectedItem.Name.Equals("Locator") || selectedItem.Name.Equals("Localizar"))
                                {
                                    Default def = new Default();
                                    BDContent.Child = def;
                                    break;
                                }
                                if (selectedItem.Name.Equals("Transaction Details") || selectedItem.Name.Equals("Transação Miudezas"))
                                {
                                    Welcome def = new Welcome();
                                    BDContent.Child = def;
                                    break;
                                }
                            }
                             
Thanks
0
Comment
Question by:razza_b
  • 26
  • 15
41 Comments
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Assuming that treeview for English and Portugese language have identical structures (same no. of nodes, node level remain same, etc.) except the text displayed in the node is different you can try doing this,

You can assign each node some unique identifier that is independent of the language. Like node representing "Locator" in English or "Localizar" in Portuguese should be assigned same id. This ID can be stored in the Tag property of the TreeNode. Thus, you can uniquely identify each node irrespecitive of the language.

Next just before language is changed, in combobox's selection changed event you can save the currently selected node's Unique Id (stored in TreeNode.Tag) in TreeView's Tag property.

While the tree is being re-populated for selected language if you find that node's unique id matches the one stored in the TreeView's Tag property then select that node.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
Hi jagrut

Yes both structures are identical except the text.

Any example of how to do tag id?

Thanks
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
If you are populating TreeView using Data binding then you can write data-binding expression for the Tag property of the TreeViewItem in XAML like,

<controls:TreeView  Name="treeView1">            
   <controls:TreeView.ItemTemplate>
       <Data:HierarchicalDataTemplate ItemsSource="{Binding Children}">
             <TextBlock Foreground="Red" Text="{Binding Name}" Tag="{Binding NODEIDPROPERTYNAME}" />                    
        </Data:HierarchicalDataTemplate>
    </controls:TreeView.ItemTemplate>
</controls:TreeView>

Open in new window


0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
yes thats what i have exactly, so if i added this..
Tag="{Binding NODEIDPROPERTYNAME}"

how does my code know how to get the id of tag?

Thanks
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
here is a snippet of code im using in treeview event..

            var selectedItem = (UserRoleTreeData.Level)e.NewValue;
            if (selectedItem != null)
            {
                foreach (UserRoleTreeData.Level item in treeView1.Items)
                {
                    #region General User Tools
                    if (item.Name.Equals("General User Tools") || item.Name.Equals("Geral Usuário Ferramentas"))
                    {
                        foreach (UserRoleTreeData.Level items in item.Children)
                        {
                            if (items != null)
                            {
                                if (selectedItem.Name.Equals("Locator") || selectedItem.Name.Equals("Localizar"))
                                {
                                    Locator loc = new Locator();
                                    BDContent.Child = loc;
                                    break;
                                }
                                if (selectedItem.Name.Equals("Transaction Details") || selectedItem.Name.Equals("Transação Miudezas"))
                                {
                                    Transaction trans= new Transaction ();
                                    BDContent.Child = trans;
                                    break;
                                }
                            }
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Please ignore the Tag based approach I proposed earlier. This can even be done without Tag. Basically you only need one private instance member in your class to store the selected tree node's unique id. This id is the unique value of each node like a Primary Key. A node's id value should be same across languages.

//This should be set to the unique Id of the selected node in "SelectedItemChanged" event of tree-view as shown below. 
//Id should be independent of the language.
private string selectedNodeId; 

private void FillTreeView()
{
    List<TreeMenu> treeMenu = new List<TreeMenu>
    {
        new TreeMenu { id="1", category = "C1", screenname = "C1_S1"},
        new TreeMenu { id="2", category = "C1", screenname = "C1_S2"},
        new TreeMenu { id="3", category = "C2", screenname = "C2_S1"},
        new TreeMenu { id="4", category = "C2", screenname = "C2_S2"},
    };

    List<UserRoleTreeData.Level> applicationMenu = (from c in treeMenu.AsQueryable()
                                                    select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

    foreach (UserRoleTreeData.Level category in applicationMenu)
    {
        var screens = (from s in treeMenu.AsQueryable()
                        where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                        select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();
        foreach (UserRoleTreeData.Level screen in screens)
            category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
    }

    treeView1.ItemsSource = applicationMenu;            
            
}

//This code will select the node with id stored in 'selectedNodeId'
private void btnGetTreeViewNode_Click(object sender, RoutedEventArgs e)
{
    //Expand all nodes. Without expanding ItemContainerGenerator fails!
    for (int i = 0; i < treeView1.Items.Count; i++)
    {
        TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
        tvi.IsExpanded = true;
    }
    treeView1.UpdateLayout();

    //Select the node
    TreeViewItem foundTvi = null;
    for (int i = 0; i < treeView1.Items.Count; i++)
    {
        TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
        foundTvi = FindNodeFromTag(selectedNodeId, treeView1.ItemContainerGenerator, tvi);
        if (foundTvi != null)
        {
            foundTvi.IsSelected = true;
            break;
        }
    }
}

//Store the id of selected node "SelectedItemChanged" event of tree-view
private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    UserRoleTreeData.Level currentSelection = e.NewValue as UserRoleTreeData.Level;
    selectedNodeId = currentSelection.Name;
}

//Function that finds node.
private TreeViewItem FindNodeFromTag(string nodeId, ItemContainerGenerator parentItemContainerGenerator, TreeViewItem treeViewItem)
{
    UserRoleTreeData.Level data;
    data = parentItemContainerGenerator.ItemFromContainer(treeViewItem) as UserRoleTreeData.Level;

    if (data.Id == nodeId)
        return treeViewItem;
    else
    {
        TreeViewItem tvi;
        for (int i = 0; i < treeViewItem.Items.Count; i++)
        {
            TreeViewItem tv = treeViewItem.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
            tvi = FindNodeFromTag(nodeId,treeViewItem.ItemContainerGenerator, tv);
            if (tvi == tv)
                return tvi;
        }

        return null;
    }
}

Open in new window


public class UserRoleTreeData
{
    public class Level
    {
        public Level(string id, string name)
        {
            Id = id;
            Name = name;
            Children = new ObservableCollection<Level>();
        }

        public string Name { get; private set; }
        public string Id { get; private set; }
        public ObservableCollection<Level> Children { get; private set; }
    }

    public class LevelComparer : IEqualityComparer<Level>
    {
        public bool Equals(Level x, Level y)
        {
            return string.Equals(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase);
        }

        public int GetHashCode(Level obj)
        {
            return obj.Name.GetHashCode();
        }
    }
}

public class TreeMenu
{
    public string id { get; set; }
    public string category { get; set; }
    public string screenname { get; set; }
}

Open in new window



XAML

<Button Name="btnFillTreeView" Click="btnFillTreeView_Click" Content="Fill Tree-view"></Button>
<controls:TreeView  Height="200" Name="treeView1" SelectedItemChanged="treeView1_SelectedItemChanged">
    <controls:TreeView.ItemTemplate>
        <Data:HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <TextBlock Foreground="Red" Text="{Binding Name}" />                    
        </Data:HierarchicalDataTemplate>
    </controls:TreeView.ItemTemplate>
</controls:TreeView>
<Button Name="btnGetTreeViewNode" Click="btnGetTreeViewNode_Click" Content="Get Tree-view Node"></Button>

Open in new window


HTH!
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
Hi Jagrut

The way i fill my tree just now is doing this..

its hidden and being clicked in main page load..
private void btnLoadDynamicTree_Click(object sender, RoutedEventArgs e)
        {
            string user = "user1";
            string lang = "ENGLISH";
            DynamicTreeClient client = new DynamicTreeClient();
            client.ListUserRolesCompleted += new EventHandler<ListUserRolesCompletedEventArgs>(client_ListUserRolesCompleted);
            client.ListUserRolesAsync(user,lang);    
        }

        void client_ListUserRolesCompleted(object sender, ListUserRolesCompletedEventArgs e)
        {
            if (e.Result.ToList().Count == 0)
            {
                Default def = new Default();
                BDContent.Child = def;
            }
            else
            {
                Welcome welcome = new Welcome();
                BDContent.Child = welcome;

                List<TreeMenu> treeMenu = e.Result.ToList();

                #region LINQ RESULT
                List<UserRoleTreeData.Level> applicationMenu =
                                    (from c in treeMenu.AsQueryable()
                                     where (c.category != "Menu Header")
                                     where (c.category != "Menu Cabeçalho")
                                     select new UserRoleTreeData.Level(c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                foreach (UserRoleTreeData.Level category in applicationMenu)
                {
                    var screens =
                                    (from s in treeMenu.AsQueryable()
                                     where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                     select new UserRoleTreeData.Level(s.screenname)).ToList();

                    foreach (UserRoleTreeData.Level screen in screens)
                        category.Children.Add(new UserRoleTreeData.Level(screen.Name));
                }
                #endregion

                treeView1.ItemsSource = applicationMenu;
            }
        }

but i see you have FillTreeView(), would that not load both langauages at the same time if im giiving everything an id?..
List<TreeMenu> treeMenu = new List<TreeMenu>
            {
                new TreeMenu { id="1", category = "General User Tools", screenname = "Locator"},
                new TreeMenu { id="2", category = "Geral Usuário Ferramentas", screenname = "Localizar"},
            };

also how does FindNodeFromTag get called? and is there code missing for the button - btnFillTreeView
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
ive put FillTreeView(), in my client_ListUserRolesCompleted just in meantime.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
i see the call FindNodeFromTag  in the btn event
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
just to let you know my tree data is being populated from DB :)
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
FindNodeFromTag gets called from btnGetTreeViewNode_Click event-handler.
btnGetTreeViewNode_Click is to show you how you can find a node based on Id and then select that node.
You need to adapt btnGetTreeViewNode_Click code such that it gets called after a tree view is populated for a choosen language.


btnFillTreeView calls FillTreeView(). Here our problem is to find way to select a node and not how the tree view is populated. I understand that your tree-view data is coming from DB. I hard-coded the data. In any case important for you to understand is "Assign same id to a node of each one language". So, rather than this

List<TreeMenu> treeMenu = new List<TreeMenu>
            {
                new TreeMenu { id="1", category = "General User Tools", screenname = "Locator"},
                new TreeMenu { id="2", category = "Geral Usuário Ferramentas", screenname = "Localizar"},
            };



it should be

List<TreeMenu> treeMenu = new List<TreeMenu>
            {
                new TreeMenu { id="1", category = "General User Tools", screenname = "Locator"},
                new TreeMenu { id="1", category = "Geral Usuário Ferramentas", screenname = "Localizar"},
            new TreeMenu { id="2", category = "General User Tools", screenname = "English1"},
                new TreeMenu { id="2", category = "Geral Usuário Ferramentas", screenname = "Portuguese1"},
            new TreeMenu { id="3", category = "General User Tools", screenname = "English2"},
                new TreeMenu { id="3", category = "Geral Usuário Ferramentas", screenname = "Portuguese2"},
            };

I don't know your complete project so can't decide best way to accomodate for Id.

0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
ok, what i see just now is that the tree loads in 2 languages at same time and when i select a child node from one i then see the other language parent node being expanded and vice versa and when debugging i see the stored selectedNodeId before its assigned new one.

But if im getting my db data out of e.result is there a way i can get to store an id of child node selection like the hard coded example?

the start of my project is tree is loaded from db by user name when mainpage loads and brings back data in english then when i choose combobox for portuguese it brings that data back, this is all done in one sp(see attachement). there are 260 rows(130 english and 130 portuguses) and the combo value brings data back related to the sp 2nd param (lang).

Thanks

project-tree-data.docx
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
ok im now doing this...
wcf code..
[OperationContract]
        public List<TreeMenu> ListUserRoles(string user,string lang)
        {            
            TreeMenu tm = new TreeMenu();
            DataSet ds = new DataSet();
            var roles = new List<TreeMenu>();
            ds = tm.getDalUserAccess2(user, lang);

            DataView dv = ds.Tables[0].DefaultView;

            if (dv != null)
                foreach (DataRowView dr in dv)
                {
                    var data = new TreeMenu
                    {
                        id = dr["ScreenID"].ToString(), // ADDED THIS
                        category = dr["Category"].ToString(),
                        screenname = dr["ScreenName"].ToString(),
                    };
                    roles.Add(data);
                }
            return roles.ToList();

I also commented out your fillTreeView method and kept my code but added the id..

//FillTreeView();
List<TreeMenu> treeMenu = e.Result.ToList();

                #region LINQ RESULT
                List<UserRoleTreeData.Level> applicationMenu =
                                    (from c in treeMenu.AsQueryable()
                                     where (c.category != "Menu Header")
                                     where (c.category != "Menu Cabeçalho")
                                     select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                foreach (UserRoleTreeData.Level category in applicationMenu)
                {
                    var screens =
                                    (from s in treeMenu.AsQueryable()
                                     where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                     select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                    foreach (UserRoleTreeData.Level screen in screens)
                        category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                }
                #endregion

                treeView1.ItemsSource = applicationMenu;

so wheni select a child node your code and my db code works.

but fails when i select other language in the FindNodeFromTag method. - argument null exception..
Value cannot be null.
Nome do parâmetro: container, the treeview item is null and i also got that when using your hard coded values. pointing at this line - data = parentItemContainerGenerator.ItemFromContainer(treeViewItem) as UserRoleTreeData.Level;
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
As the error says, parentItemContainerGenerator.ItemFromContainer is failing because its argument "treeViewItem" is null.

FindNodeFromTag() function accepts treeViewItem as an argument. Check all calls to this function in debug mode to identify whether any call passes null for the 3rd argument. I never get this exception with my hard-coded data.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
ok its when i select node fro first time thats fine it stores the id if node, when changing to other language im getting obj ref not set to instance of obj at this line in bold currentSelection is null..

private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            btnGetTreeViewNode_Click(null, null);
            UserRoleTreeData.Level currentSelection = e.NewValue as UserRoleTreeData.Level;            
            selectedNodeId = currentSelection.Id;


the tvi is fine i see data for that for third arg.

So i dont know if its when changing language its not selecting node? because first time round this code is fine.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
This is all the code can you see what im doing wrong?
private void btnGetTreeViewNode_Click(object sender, RoutedEventArgs e)
        {
            //Expand all nodes. Without expanding ItemContainerGenerator fails!
            for (int i = 0; i < treeView1.Items.Count; i++)
            {
                TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                tvi.IsExpanded = true;
            }
            treeView1.UpdateLayout();

            //Select the node
            TreeViewItem foundTvi = null;
            for (int i = 0; i < treeView1.Items.Count; i++)
            {
                TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                foundTvi = FindNodeFromTag(selectedNodeId, treeView1.ItemContainerGenerator, tvi);
                if (foundTvi != null)
                {
                    foundTvi.IsSelected = true;
                    break;
                }
            }
        }

Open in new window

private TreeViewItem FindNodeFromTag(string nodeId, ItemContainerGenerator parentItemContainerGenerator, TreeViewItem treeViewItem)
        {
            UserRoleTreeData.Level data;
           
            data = parentItemContainerGenerator.ItemFromContainer(treeViewItem) as UserRoleTreeData.Level;

            if (data.Id == nodeId)
                return treeViewItem;
            else
            {
                TreeViewItem tvi;
                for (int i = 0; i < treeViewItem.Items.Count; i++)
                {
                    TreeViewItem tv = treeViewItem.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                    tvi = FindNodeFromTag(nodeId,treeViewItem.ItemContainerGenerator, tv);
                    if (tvi == tv)
                        return tvi;
                }

                return null;
            }
        }

Open in new window

private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            btnGetTreeViewNode_Click(null, null);
            UserRoleTreeData.Level currentSelection = e.NewValue as UserRoleTreeData.Level;
            
            selectedNodeId = currentSelection.Id;
            ....

Open in new window

public class TreeMenu
    {
        private string _screenname;
        private string _category;
        private string _id;

        public TreeMenu()
        {
        }
        public string screenname
        {
            get { return _screenname; }
            set { _screenname = value; }
        }
        public string category
        {
            get { return _category; }
            set { _category = value; }
        }
        public string id
        {
            get { return _id; }
            set { _id = value; }
        }

Open in new window

public class UserRoleTreeData
    {
        public class Level
        {
            public Level(string id, string name)
            {
                Id = id;
                Name = name;
                Children = new ObservableCollection<Level>();
            }

            public string Name { get; private set; }
            public string Id { get; private set; }
            public ObservableCollection<Level> Children { get; private set; }

            public bool IsExpanded { get; set; }
        }

        public class LevelComparer : IEqualityComparer<Level>
        {
            public bool Equals(Level x, Level y)
            {
                return string.Equals(x.Name, y.Name, StringComparison.InvariantCultureIgnoreCase);
            }

            public int GetHashCode(Level obj)
            {
                return obj.Name.GetHashCode();
            }
        }
    }

Open in new window

void client_ListUserRolesCompleted(object sender, ListUserRolesCompletedEventArgs e)
        {
            if (e.Result.ToList().Count == 0)
            {
                Default def = new Default();
                BDContent.Child = def;
            }
            else
            {
                Welcome welcome = new Welcome();
                BDContent.Child = welcome;

                //FillTreeView();

                List<TreeMenu> treeMenu = e.Result.ToList();

                #region LINQ RESULT
                List<UserRoleTreeData.Level> applicationMenu =
                                    (from c in treeMenu.AsQueryable()
                                     where (c.category != "Menu Header")
                                     where (c.category != "Menu Cabeçalho")
                                     select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                foreach (UserRoleTreeData.Level category in applicationMenu)
                {
                    var screens =
                                    (from s in treeMenu.AsQueryable()
                                     where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                     select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                    foreach (UserRoleTreeData.Level screen in screens)
                        category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                }
                #endregion

                treeView1.ItemsSource = applicationMenu;
            }
        }

Open in new window

0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
I'm not getting why did you called  btnGetTreeViewNode_Click from treeView1_SelectedItemChanged.

Code that I gave you for btnGetTreeViewNode_Click was just to show you how a node can be selected in a "particular" tree-view.
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Your comment "ok, what i see just now is that the tree loads in 2 languages at same time and when i select a child node from one i then see the other language parent node being expanded and vice versa...." is very confusing...I cannot give you exact code changes you need to make w/o debugging your current code.

0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
The reason i called button click was just to get the selected node i had it hidden when i select a node so that it would store its id value to match when language changed.
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Sorry razza, but I'm gradually losing the track of your problem. It's getting very confusing now!

Functionality shown in "btnGetTreeViewNode_Click" should be called when you need to select a node with id = selectedNodeId. Thus, you should not be calling it from treeView1_SelectedItemChanged.

Your UI flow is like this:
1. Tree-view gets loaded for English language
2. Language drop-down show English and Portuguese
3. Say now user selects Portuguese
4. So tree-view reloads for Portuguese language

After (4) is done (i.e. ensure that data for choosen language are populated in tree) put code that calls "btnGetTreeViewNode_Click" like
if(selectedNodeId != null)
  btnGetTreeViewNode_Click(null, null)


From treeView1_SelectedItemChanged remove "btnGetTreeViewNode_Click(null, null)". It is not required there. Run your application in debug mode and check that for a particular node selectedNodeId gets same value for Id.
E.g. if you select "Menu Header" say in selectedNodeId you get "100". Then when you select "Menu Cabeçalho" you should also get "100" in selectedNodeId.

0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 1

Author Comment

by:razza_b
Comment Utility
Hi Jagrut yes im a bit lost myself too, where should i be calling the button click event from then? because anytime i reload the tree with other language this always seems to be null and i get obj ref not set to instance of obj..
UserRoleTreeData.Level currentSelection = e.NewValue as UserRoleTreeData.Level;
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
its as if when changing language the selected tree item gets unselected for it to be null.

even though its null and cant even assign the selectedNodeId to currentSelection because the set accessor is inaccessible.
0
 
LVL 8

Accepted Solution

by:
jagrut_patel earned 500 total points
Comment Utility
1. The "currentSelection" variable has  to be a instance member of a class and not method's local variable. You should declare it as member of the class that hosts/loads a tree-view.
2. "currentSelection" needs to store a value type like integer and not a refrence type. Idea is to store unique identification value of a node. Thus the node identifier will not be nullified when tree is reloaded.
3. button click code should be called after tree is loaded. Take care that if there "currentSelection" is empty/null there is no point in calling button click code that selects a node because it means no node was selected by the user.

Just to target the problem in chunks you first forget about calling the button click code. First debug to ensure that "currentselection" variable is correctly assigned when you select a node and re-load the tree in different language. Ensure that the value that gets stored in this variable is exactly a unique id of a node. Such node identification value should be unique across the language.

Once this is verified thereafter you can add the "button click" like code to persist node selection.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
Hi Jagrut

ok at the moment im not using button click, but i doing this just now in treeView1_SelectedItemChanged..
snippet..
            if (currentSelection == null)
            {
                currentSelection = e.NewValue as UserRoleTreeData.Level;
                selectedNodeId = currentSelection.Id;
                // go get name of page and display....
            }
            else if (currentSelection.Id != null)
            {                
                // go get name of page and display....

when i select other language currentSelection is stored,so if i where now to introduce the button click, will this now keep the page content shown(node selected) and tree expanded?

Is this what you where meaning?

Thanks
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
made a bit of a breakthrough without button click, ive got the page selected staying the same when changing langauge, but tree isnt collapsed, so its just a matter of keeping tree collapsed and still showing the node selected.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
when i select back to other langauge again it then doesnt keep node selected(page shown) due to tree not collapesd and keeping node selected, if you follow.
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Now to keep node selected when language is switched, you can add code of button click such that it is called "just after tree is populated".
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
Im still not getting the tree to stay expanded and keep node selected shown when language has changed, im using the button click after tree re-loads. I call the button code in the combo code after it has got the data to reload tree.

any ideas?
private void cmbLang_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (comboBox1 == null) return;
            switch ((e.AddedItems[0] as ListBoxItem).Content.ToString())
            {
                case "ENGLISH":
                    var culture1 = new CultureInfo("en-US");
                    Thread.CurrentThread.CurrentCulture = culture1;
                    Thread.CurrentThread.CurrentUICulture = culture1;
                    string user = "user";
                    string lang = "ENGLISH";
                    DynamicTreeClient client = new DynamicTreeClient();
                    client.ListUserRolesCompleted += new EventHandler<ListUserRolesCompletedEventArgs>(client_ListUserRolesCompleted);
                    client.ListUserRolesAsync(user,lang);
                    btnGetTreeViewNode_Click(null, null);
                    break;
                case "PORTUGUESE":
                    var culture2 = new CultureInfo("pt-BR");
                    Thread.CurrentThread.CurrentCulture = culture2;
                    Thread.CurrentThread.CurrentUICulture = culture2;
                    string user2 = "user";
                    string lang2 = "PORTUGUESE";
                    DynamicTreeClient client2 = new DynamicTreeClient();
                    client2.ListUserRolesCompleted += new EventHandler<ListUserRolesCompletedEventArgs>(client_ListUserRolesCompleted);
                    client2.ListUserRolesAsync(user2,lang2);
                    btnGetTreeViewNode_Click(null, null);
                    break;
}

Open in new window

void client_ListUserRolesCompleted(object sender, ListUserRolesCompletedEventArgs e)
        {
            if (e.Result.ToList().Count == 0)
            {
                Default def = new Default();
                BDContent.Child = def;
            }
            else if (currentSelection == null)
            {
                Welcome welcome = new Welcome();
                BDContent.Child = welcome;

                //FillTreeView();

                List<TreeMenu> treeMenu = e.Result.ToList();

                #region LINQ RESULT
                List<UserRoleTreeData.Level> applicationMenu =
                                    (from c in treeMenu.AsQueryable()
                                     where (c.category != "Menu Header")
                                     where (c.category != "Menu Cabeçalho")
                                     select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                foreach (UserRoleTreeData.Level category in applicationMenu)
                {
                    var screens =
                                    (from s in treeMenu.AsQueryable()
                                     where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                     select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                    foreach (UserRoleTreeData.Level screen in screens)
                        category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                }
                #endregion

                treeView1.ItemsSource = applicationMenu;

            }
            else if (currentSelection.Id != null)
            {
                selectedNodeId = currentSelection.Id;
                if (selectedNodeId != null)
                {

                    List<TreeMenu> treeMenu = e.Result.ToList();

                    #region LINQ RESULT
                    List<UserRoleTreeData.Level> applicationMenu =
                                        (from c in treeMenu.AsQueryable()
                                         where (c.category != "Menu Header")
                                         where (c.category != "Menu Cabeçalho")
                                         select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                    foreach (UserRoleTreeData.Level category in applicationMenu)
                    {
                        var screens =
                                        (from s in treeMenu.AsQueryable()
                                         where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                         select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                        foreach (UserRoleTreeData.Level screen in screens)
                            category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                    }
                    #endregion
                    
                    treeView1.ItemsSource = applicationMenu;
                    //btnGetTreeViewNode_Click(null, null);
                }
            }       
        }

Open in new window

0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
OK, i now have it working, content page stays selected with appropiate langauge content. i realized i had assigned wrong value in validation of tree code.

the only thing is tree stays collapsed which i dont mind, i'd rather it stay collapsed than expanded.

Although i would like it to just expnd the parent node only from where child is selected rather than evry parent expanded or none.
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
You cannot call button click after "ListUserRolesAsync". You should call it at the end of "client_ListUserRolesCompleted" method like this,

void client_ListUserRolesCompleted(object sender, ListUserRolesCompletedEventArgs e)
{
  //Your code as shown above
  //At the end write

 if (!string.IsNullOrEmpty(selectedNodeId))
    btnGetTreeViewNode_Click(null, null);

}

Open in new window


 
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
i get the "obj ref not set to aninstance of obj" at the line when i add the code above as you mentioned...

TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
tvi.IsExpanded = true;
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
and if i do this the tree stays expanded but nothing changes to the selected language...


if (string.IsNullOrEmpty(selectedNodeId) || (string.IsNullOrEmpty(currentSelection.Id)))
            {
                if (e.Result.ToList().Count == 0)
                {
                    Default def = new Default();
                    BDContent.Child = def;
                }
                else if (currentSelection == null)
                {
                    Welcome welcome = new Welcome();
                    BDContent.Child = welcome;

                    List<TreeMenu> treeMenu = e.Result.ToList();

                    #region LINQ RESULT
                    List<UserRoleTreeData.Level> applicationMenu =
                                        (from c in treeMenu.AsQueryable()
                                         where (c.category != "Menu Header")
                                         where (c.category != "Menu Cabeçalho")
                                         select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                    foreach (UserRoleTreeData.Level category in applicationMenu)
                    {
                        var screens =
                                        (from s in treeMenu.AsQueryable()
                                         where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                         select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                        foreach (UserRoleTreeData.Level screen in screens)
                            category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                    }
                    #endregion

                    treeView1.ItemsSource = applicationMenu;

                }
                else if (currentSelection != null)
                {
                    selectedNodeId = currentSelection.Id;
                    if (selectedNodeId != null)
                    {

                        List<TreeMenu> treeMenu = e.Result.ToList();

                        #region LINQ RESULT
                        List<UserRoleTreeData.Level> applicationMenu =
                                            (from c in treeMenu.AsQueryable()
                                             where (c.category != "Menu Header")
                                             where (c.category != "Menu Cabeçalho")
                                             select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                        foreach (UserRoleTreeData.Level category in applicationMenu)
                        {
                            var screens =
                                            (from s in treeMenu.AsQueryable()
                                             where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                             select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                            foreach (UserRoleTreeData.Level screen in screens)
                                category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                        }
                        #endregion

                        treeView1.ItemsSource = applicationMenu;
                        
                    }
                }
            }
            else if (!string.IsNullOrEmpty(selectedNodeId) || (!string.IsNullOrEmpty(currentSelection.Id)))
            {
                btnGetTreeViewNode_Click(null, null);
            }

Open in new window

0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
Ive also noticed that if i have selected a child node in whatever language and then select its parent node(with one click to highlight it) then change the language again the content page is still in previous langauge even though the tree langauge is fine, is there a way to stop the parent node having an id to prevent this from happening? so that the stored id of child remains.

and is there a way to prevent a parent node being double clicked so that it doesnt expand?

Thanks
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Please post code corresponding to your comment ID "36524127".
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
same code as you posted..

private void btnGetTreeViewNode_Click(object sender, RoutedEventArgs e)
        {
            //Expand all nodes. Without expanding ItemContainerGenerator it fails!
            for (int i = 0; i < treeView1.Items.Count; i++)
            {
                TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                tvi.IsExpanded = true;
            }
            treeView1.UpdateLayout();

            //Select the node
            TreeViewItem foundTvi = null;
            for (int i = 0; i < treeView1.Items.Count; i++)
            {
                TreeViewItem tvi = treeView1.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                foundTvi = FindNodeFromTree(selectedNodeId, treeView1.ItemContainerGenerator, tvi);
                if (foundTvi != null)
                {
                    foundTvi.IsSelected = true;
                    break;
                }
            }
        }

Open in new window

0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Not that.

I am asking for the code you wrote as per my suggestion for "client_ListUserRolesCompleted" but you got ObjectReferenceException.

" get the "obj ref not set to aninstance of obj" at the line when i add the code above as you mentioned..."
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
sorry.

its when i had it just like that..
if (e.Result.ToList().Count == 0)
                {
                    Default def = new Default();
                    BDContent.Child = def;
                }
                else if (currentSelection == null)
                {
                    Welcome welcome = new Welcome();
                    BDContent.Child = welcome;

                    List<TreeMenu> treeMenu = e.Result.ToList();

                    #region LINQ RESULT
                    List<UserRoleTreeData.Level> applicationMenu =
                                        (from c in treeMenu.AsQueryable()
                                         where (c.category != "Menu Header")
                                         where (c.category != "Menu Cabeçalho")
                                         select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                    foreach (UserRoleTreeData.Level category in applicationMenu)
                    {
                        var screens =
                                       (from s in treeMenu.AsQueryable()
                                        where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                        select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                        foreach (UserRoleTreeData.Level screen in screens)
                            category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                    }
                    #endregion

                    treeView1.ItemsSource = applicationMenu;

                }
                else if (currentSelection != null)
                {
                    selectedNodeId = currentSelection.Id;
                    if (selectedNodeId != null)
                    {

                        List<TreeMenu> treeMenu = e.Result.ToList();

                        #region LINQ RESULT
                        List<UserRoleTreeData.Level> applicationMenu =
                                            (from c in treeMenu.AsQueryable()
                                             where (c.category != "Menu Header")
                                             where (c.category != "Menu Cabeçalho")
                                             select new UserRoleTreeData.Level(c.id, c.category)).Distinct(new UserRoleTreeData.LevelComparer()).ToList();

                        foreach (UserRoleTreeData.Level category in applicationMenu)
                        {
                            var screens =
                                            (from s in treeMenu.AsQueryable()
                                             where string.Equals(s.category, category.Name, StringComparison.InvariantCultureIgnoreCase)
                                             select new UserRoleTreeData.Level(s.id, s.screenname)).ToList();

                            foreach (UserRoleTreeData.Level screen in screens)
                                category.Children.Add(new UserRoleTreeData.Level(screen.Id, screen.Name));
                        }
                        #endregion
                       
                        treeView1.ItemsSource = applicationMenu;
                        if (!string.IsNullOrEmpty(selectedNodeId) || (!string.IsNullOrEmpty(currentSelection.Id)))
                        {
                            btnGetTreeViewNode_Click(null, null);
                        }
                    }
                }

Open in new window

0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Ok now. I get the same error.

That exception occurs because button click code gets called before treeview.ITemSource has completed loading of the tree-view nodes.

I do not have solution for this yet. I'll be looking for one. May we need some replacement of "TargetUpdated" of WPF in Silverlight.
0
 
LVL 1

Author Comment

by:razza_b
Comment Utility
ok, i've never used wpf, im still getting to grips with SL.
0
 
LVL 1

Author Closing Comment

by:razza_b
Comment Utility
Jagrut

I going to accept this even though the tree doesnt stay expanded, id rather it stay collapsed, plus i have it with the selected content changed to the preferred language. and i just call btn click after tree loaded in my combo, but all looks good :), hope you get the error sorted on the expand tree.
0
 
LVL 8

Expert Comment

by:jagrut_patel
Comment Utility
Thank you Razza. If I'll find any solution I will surely post it here.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Total in textboxes 9 34
Exception in Log4Net 1 17
Why don't I see this table in EDMX file? 2 19
Format column on datatable 7 14
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now