views:

637

answers:

2

I'm sure there is something simple that I am missing, but I must confess that at this point I am at a loss.

I am programmatically adding TabItems to my main TabControl, one for each account that the user chooses to open. Before creating and adding a new TabItem I would like to check if the user already has the account open in another tab. I do not want to end up with two identical tabs open.

Here is the code that I originally wrote. Hopefully it gives you an idea of what I am trying to accomplish.

    if (tab_main.Items.Contains(accountNumber))
    {
        tab_main.SelectedIndex = tab_main.Items.IndexOf(accountNumber);
    }
    else
    {
        Search s = new Search(queryResults, searchText);
        TabItem tab_search = new TabItem();
        tab_search.Header = searchString;
        tab_search.Name = accountNumber;
        tab_search.Content = s;
        tab_main.Items.Add(tab_search);
    }

Of course this doesn't work properly. In WinForms the TabControl has a TabPages collection with a ContainsKey method that I could use to search for the name of the TabPage. I don't get what the Items.Contains() method is looking for since it only specifies an object as an argument and doesn't reference the item's name!

Any and all help is greatly appreciated.

Thanks!

+1  A: 

The Contains() method is looking for you to pass in the actual TabItem you are looking for, so it won't help you. But this will work:

var matchingItem =
  tab_main.Items.Cast<TabItem>()
    .Where(item => item.Name == accountNumber)
    .FirstOrDefault();

if(matchingItem!=null)
  tab_main.SelectedItem = matchingItem;
else
  ...
Ray Burns
Ray, I took the liberty of editing in a call to `Cast`. TabControl.Items is `IEnumerable` but not `IEnumerable<T>` so it doesn't directly support the LINQ Where operator directly.
itowlson
Thank you. ----
Ray Burns
Thanks for the replies! Before the edit it didn't work and I ended up coming up with another similar solution. Certainly got me thinking in the right direction! I found a very similar solution but also had one follow up question that I will post as another answer if anyone has the time to help!
Terminal Frost
A: 

Thanks for the replies! Before the edit it didn't work and I ended up coming up with another similar solution. Certainly got me thinking in the right direction! I'm still not quite used to LINQ and lambda expressions.

In case anyone else is looking for solutions this also worked for me:

var matchingItem = 
    from TabItem t in tab_main.Items where t.Name == searchHash select t;

if (matchingItem.Count() != 0)
    tab_main.SelectedItem = matchingItem.ElementAt(0);
else
    ...

One final question if anyone is reading this... is there a more elegant way to select the element from matchingItem by referencing the name property versus assuming the correct element is at position 0?

Terminal Frost
There is not necessarily a "correct element" - more than one element can have the same Name property. If the names are registered using `INameScope.RegisterName`, then `INameScope.FindName` will find it. However this is not a good design for several reasons which I will not enumerate here. With WPF you should be using MVVM design, not old WinForms-style design. Look around StackOverflow and elsewhere to learn about MVVM.
Ray Burns
FYI: in general Stack Overflow encourages users to ask "follow up" questions as new questions rather than extending their existing questions. See the FAQ and discussions in meta.stackoverflow.com for more information.
Ray Burns
Cool thanks for the correction and pointing me to MVVM design.
Terminal Frost