1

In my program I have a tabItem that gets selected when a TreeViewItem with an equivalent header is selected.

This is what I currently have (It works):

(parent_TreeViewItem.Items.Contains(SelectedItem))
{
          tabControl1.SelectedItem = tabControl1.Items //Changes tab according to TreeView
                .OfType<TabItem>().SingleOrDefault(n => n.Header.ToString() == SelectedItem.Header.ToString());
}

The difference with what I'm doing this time is that the tabItem's header that I'm selecting is composed of a string and an integer.

For example: The TreeViewItem selected will always have a header named "Arrival", but the tabItem's header will have a form like "Arrival" + integer. The integer value will come from the parent node's header.

For this process I'm thinking that I'll first need to get the header value of the parent node, since it contains that integer value I need. Then I'll need to modify my code above in someway to query for a node with a header like, "Arrival" + parentHeader.

How would I do something like this?

Thank you.

UPDATE

My current code, using @varocarbas's answer. I am using the first version of the answer that involved setting the integer curNumber to the value of the parent's header. The code compiles but does not do anything when the "Arrival" node is clicked on.

if (parent_TreeViewItem.Items.Contains(SelectedItem.Parent)) //Location - Actions tabs
{
       TreeViewItem parentItem = (TreeViewItem)SelectedItem.Parent;
       int curNumber = getNumber(parentItem.Header.ToString());

       tabControl1.SelectedItem = tabControl1.Items //Changes tab according to TreeView
             .OfType<TabItem>().SingleOrDefault(n => n.Header.ToString() == SelectedItem.Header.ToString() + curNumber.ToString());
}

public static int getNumber(string parentNodeHeader)
{
    int curNumber = 0;
    curNumber = Convert.ToInt32(parentNodeHeader);

    return curNumber;
}

UPDATE 2: Because the "Arrival" node is the grandchild of the node I was using as a parent I have changed the if statement in my first line to:

 if (parent_TreeViewItem.Items.Contains(SelectedItem.Parent))
Eric after dark
  • 1,768
  • 4
  • 31
  • 79
  • 1
    So instead of using `n.Header.ToString() = ...` why not using [String.StartsWith()](http://msdn.microsoft.com/en-us/library/baketfxw.aspx). Something like `n.Header.ToString().StartsWith(SelectedItem.Header.ToString())` – Viv Aug 21 '13 at 15:47
  • Are there different "Arrival" + number? That is, you need to know the exact number or "Arrival" is the only important bit? – varocarbas Aug 21 '13 at 15:49
  • There will be more than one number. Like there's an arrival tab for multiple locations. – Eric after dark Aug 21 '13 at 15:50

1 Answers1

1

Firstly, you have to get the parent node and the number contained in its header:

TreeViewItem parentItem = (TreeViewItem)selectedItem.Parent;
int curNumber = getNumber(parentItem.Header.ToString());

getNumber is a function to retrieve the number from its exact location in the parent node header. You have to tell more about that in order to write a proper function; for the time being, just the basics (it extracts all the numbers in the input string):

private int getNumber(string parentNodeHeader)
{
    int curNumber = 0;

    //Required string-analysis actions
    //Sample functionality: extract all the numbers in the given string
    string outString = "";
    int count = -1;
    do
    {
        count = count + 1;
        Char curChar = Convert.ToChar(parentNodeHeader.Substring(count, 1));
        if (Char.IsNumber(curChar))
        {
            outString = outString + parentNodeHeader.Substring(count, 1);
        }
    } while (count < parentNodeHeader.Length - 1);

    if (outString != "")
    {
        curNumber = Convert.ToInt32(outString);
    }

    return curNumber;
}

And then you have to update the query to account for the new information:

 .OfType<TabItem>().SingleOrDefault(n => n.Header.ToString() == selectedItem.Header.ToString() + curNumber.ToString());

UPDATE

The function above just shows the kind of code I usually rely on; but for simple situations (like the proposed one of getting all the numbers in a string), you might prefer to rely on Regex, as suggested by Viv. You might rely on something on the lines of:

private int getNumber(string parentNodeHeader)
{
    System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(parentNodeHeader, @"\d+");
    return Convert.ToInt32(m.Value);
}

This function only delivers the first set of consecutive numbers it finds; different result than the function above but enough as a proof of concept (intention of this answer).

varocarbas
  • 12,354
  • 4
  • 26
  • 37
  • why would you prefer to write a function to extract a number than just use a `Regex` and capture the number out? – Viv Aug 21 '13 at 16:33
  • @Viv I prefer functions/loops because are much more clear, extensible and adaptable, IMO. For a simple situation, Regex is clearly much more efficient; but I am not sure about the exact requirements in this case; also I am pretty used to deal with complex situations and thus I tend to write loops/functions by default (bigger code but systematic writing taking me a pretty short time) :) – varocarbas Aug 21 '13 at 16:37
  • @Viv I have updated my answer with some Regex. Although it shows the kind of limitations I was referring in my last comment: a really simple regex is acceptable but only for very specific conditions. The one I wrote is for consecutive numbers; if you want to account for any number in any position, like in my loop; you would have to make it more complex. On the other hand, my loop can easily deliver any number or just consecutive ones: once the structure is in place, extending/improving it is relatively simple. – varocarbas Aug 21 '13 at 16:47
  • @varocarbas Please take a look at my question. I've implemented the first version of your answer, but it isn't effecting any change, which confuses me because it looks like everything is correct. Should I scrap it and use the new `getNumber` function? – Eric after dark Aug 21 '13 at 17:19
  • @Ericafterdark with the new one you mean the Regex-based one? Go ahead if you wish; but the first function (the one with the loop) should work without any problem. Please set a break point and confirm that the inputs/outputs of the function are the expected ones. – varocarbas Aug 21 '13 at 17:28
  • Should the one in the update in my question be working? Because if it's just going to take some debugging I'd rather stick with that one because of the simplicity. – Eric after dark Aug 21 '13 at 17:31
  • 1
    @Ericafterdark the function in the upate returns the first set of consecutive numbers it finds. For example: in ab1cd32, returns 1 or in 123bdc5 123. If this is what you want, go ahead. The function with the loop returns all the numbers it finds; in the last examples: 132 and 1235. I am not sure which one of these functionalities are you after (if any). In any case, I recommend you to do a debugging to make sure that everything works as intended. – varocarbas Aug 21 '13 at 17:36
  • @varocarbas I think I found out what the problem is. Your code works, but the parent node that I check for the "Arrival" node is actually a grandparent to the "Arrival" node. I thought that no matter the descendant level, as long as a node was a related child it would be "contained" by any parent above it. It's working now. Thanks. I made another update in my question if you'd like to check it out. – Eric after dark Aug 21 '13 at 17:47