Link to home
Start Free TrialLog in
Avatar of razza_b
razza_b

asked on

save selected child node

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
Avatar of jagrut_patel
jagrut_patel
Flag of India image

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.
Avatar of razza_b
razza_b

ASKER

Hi jagrut

Yes both structures are identical except the text.

Any example of how to do tag id?

Thanks
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


Avatar of razza_b

ASKER

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
Avatar of razza_b

ASKER

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;
                                }
                            }
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!
Avatar of razza_b

ASKER

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
Avatar of razza_b

ASKER

ive put FillTreeView(), in my client_ListUserRolesCompleted just in meantime.
Avatar of razza_b

ASKER

i see the call FindNodeFromTag  in the btn event
Avatar of razza_b

ASKER

just to let you know my tree data is being populated from DB :)
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.

Avatar of razza_b

ASKER

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
Avatar of razza_b

ASKER

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;
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.
Avatar of razza_b

ASKER

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.
Avatar of razza_b

ASKER

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

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.
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.

Avatar of razza_b

ASKER

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.
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.

Avatar of razza_b

ASKER

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;
Avatar of razza_b

ASKER

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.
ASKER CERTIFIED SOLUTION
Avatar of jagrut_patel
jagrut_patel
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of razza_b

ASKER

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
Avatar of razza_b

ASKER

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.
Avatar of razza_b

ASKER

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.
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".
Avatar of razza_b

ASKER

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

Avatar of razza_b

ASKER

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.
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


 
Avatar of razza_b

ASKER

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;
Avatar of razza_b

ASKER

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

Avatar of razza_b

ASKER

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
Please post code corresponding to your comment ID "36524127".
Avatar of razza_b

ASKER

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

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..."
Avatar of razza_b

ASKER

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

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.
Avatar of razza_b

ASKER

ok, i've never used wpf, im still getting to grips with SL.
Avatar of razza_b

ASKER

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.
Thank you Razza. If I'll find any solution I will surely post it here.