Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create, refresh a WPF TreeView and remember expanded nodes without XAML

I am currently upgrading the tool of my predecessor and I'm stuck on a TreeView issue. His software analyzed data one time and displayed the results in a TreeView. I changed the tool to analyze real-time data and hence the user gets real time results. Now, I would like the tree view nodes to keep expanded when the user expands it, even after an update. I know this topic has been discussed several times and I spent hours reading the answers but I never found a solution for my problem.

The basic problem is: there is no stable tree any more and currently the tree is just re-created every time. I have no idea about data binding or XAML up to now and few time to learn programming in XAML. Below you can see the code like it was created by my predecessor. I did not change anything up to now, I just recall this method every 2-5 seconds.

Is there an (easy?) way to store the information about expanded nodes anywhere (global?) and re-expand it after refresh or do I really need to get a deeper understanding of WPF first?

foreach (Analyzer.ALARM_GROUP alarmGroup in alarmGroupList)
{
    //Display Problem Group
    TreeViewItem groupItem = new TreeViewItem();
    List<String> ListAreas = new List<string>();
    string areas = "";

    //GROUP HEADER
    //display alarm group which contains more than one alarm
    if (alarmGroup.AlarmList.Count > 1)
    {
        groupItem.Header = Convert.ToString(alarmGroup.AlarmList.Count) + " --- " + alarmGroup.AlarmList[0].EventTime + "     " + alarmGroup.AlarmList[0].AlarmText + "\n         "
                    + alarmGroup.AlarmList[alarmGroup.AlarmList.Count - 1].EventTime + "     " + alarmGroup.AlarmList[alarmGroup.AlarmList.Count - 1].AlarmText
                    + " --- " + " AREAS: " + areas;
    }
    else //display alarm group with only one alarm message
    {
        groupItem.Header = Convert.ToString(alarmGroup.AlarmList.Count) + " --- " + alarmGroup.AlarmList[0].EventTime + "     " + alarmGroup.AlarmList[0].AlarmText + " --- " + " AREA: " + areas;
    }

    //HEADLINE of single Alarm Item
    TreeViewItem alarmItem = new TreeViewItem();
    alarmItem.Header = "[EVENTTIME]                           [ALARMTAG] --- [OPCCONDITION] --- [SEVERITY] --- [AREA] --- [ALARMTEXT]";
    alarmItem.FontWeight = FontWeights.SemiBold;
    groupItem.Items.Add(alarmItem);

    //Display single alarm messages
    foreach (var alarm in alarmGroup.AlarmList)
    {
        alarmItem = new TreeViewItem();
        alarmItem.Header = alarm.EventTime + " --- " + alarm.AlarmTag + " --- " + alarm.Condition + " --- " + alarm.Severity + " --- " + alarm.Area + " --- " + alarm.AlarmText;
        alarmItem.FontWeight = FontWeights.Normal;
        groupItem.Items.Add(alarmItem);
    }

    AlarmPresentationBox.Items.Add(groupItem); 
like image 397
Larimow Avatar asked Jul 18 '12 11:07

Larimow


1 Answers

do I really need to get a deeper understanding of WPF first?

I would say Yes, specially in case you are planning to work/support this application for longer period of time; and if you would like to work in WPF in future then it's better to get your hands dirty with XAML and WPF concepts.

Personally, I would never implement this tool this way, instead I would go for MVVM approch as described in following article and make it clean, maintainable and efficient - Simplifying the WPF TreeView by Using the ViewModel Pattern

Is there an (easy?) way to store the information about expanded nodes anywhere (global?) and re-expand it after refresh

You can try something like this -

Create a list to store the header(or any unique property/id) of expanded nodes

private List<string> expandedNodes = new List<string>();

Handle the Expanded and Collapsed event of each node(having child nodes)

TreeViewItem alarmItem = new TreeViewItem();
alarmItem.Expanded += OnAlarmItemExpanded;

Update the list whenever node is expanded/collapsed -

private void OnAlarmItemExpanded(object sender, RoutedEventArgs e)
{
    TreeViewItem treeNode = sender as TreeViewItem;
    string header = treeNode.Header.ToString();
    if (expandedNodes.Contains(header) == false)
    {
        expandedNodes.Add(header);
    }
}

private void OnAlarmItemCollapsed(object sender, RoutedEventArgs e)
{
    TreeViewItem treeNode = sender as TreeViewItem;
    string header = treeNode.Header.ToString();
    if (expandedNodes.Contains(header))
    {
        expandedNodes.Remove(header);
    }
} 

Next time whenever you create a TreeViewItem, expand it if it's header(Uniques Id) is present in list -

if (expandedNodes.Contains(header))
{
    alarmItem.IsExpanded = true;
}

This needs to be done for both groupItem and alarmItem.

like image 60
akjoshi Avatar answered Nov 10 '22 09:11

akjoshi