WPF / C #: как ссылаться на TabItems внутри TabControl?

Я уверен, что мне не хватает чего-то простого, но должен признаться, что на данный момент я в растерянности.

Я программно добавляю TabItems в свой основной TabControl, по одному для каждой учетной записи, которую пользователь выбирает открыть. Перед созданием и добавлением нового элемента вкладки я хотел бы проверить, есть ли у пользователя уже открытая учетная запись на другой вкладке. Я не хочу, чтобы открывались две одинаковые вкладки.

Вот код, который я написал изначально. Надеюсь, это даст вам представление о том, чего я пытаюсь достичь.

    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);
    }

Конечно, это не работает должным образом. В WinForms TabControl имеет коллекцию TabPages с методом ContainsKey, который я мог бы использовать для поиска имени TabPage. Я не понимаю, что ищет метод Items.Contains (), поскольку он только указывает объект в качестве аргумента и не ссылается на имя элемента!

Любая помощь приветствуется.

Спасибо!


person Jeff Camera    schedule 17.02.2010    source источник


Ответы (2)


Метод Contains() ищет вас для передачи фактического TabItem, который вы ищете, поэтому он вам не поможет. Но это сработает:

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

if(matchingItem!=null)
  tab_main.SelectedItem = matchingItem;
else
  ...
person Ray Burns    schedule 17.02.2010
comment
Рэй, я взял на себя смелость редактировать, позвонив Cast. TabControl.Items - это IEnumerable, но не IEnumerable<T>, поэтому он не поддерживает напрямую оператор LINQ Where. - person itowlson; 17.02.2010
comment
Спасибо за ответы! До редактирования это не сработало, и я пришел к другому аналогичному решению. Конечно, заставил меня думать в правильном направлении! Я нашел очень похожее решение, но у меня был еще один вопрос, который я отправлю в качестве другого ответа, если у кого-то будет время помочь! - person Jeff Camera; 17.02.2010

Спасибо за ответы! До редактирования это не сработало, и я пришел к другому аналогичному решению. Конечно, заставил меня думать в правильном направлении! Я все еще не совсем привык к LINQ и лямбда-выражениям.

Если кто-то еще ищет решения, это тоже сработало для меня:

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

И последний вопрос, если кто-нибудь это читает ... есть ли более элегантный способ выбрать элемент из MatchItem, указав свойство name, а не предполагать, что правильный элемент находится в позиции 0?

person Jeff Camera    schedule 17.02.2010
comment
Это не обязательно правильный элемент - несколько элементов могут иметь одно и то же свойство Name. Если имена зарегистрированы с использованием INameScope.RegisterName, то INameScope.FindName найдет его. Однако это плохой дизайн по нескольким причинам, которые я здесь не буду перечислять. В WPF вы должны использовать дизайн MVVM, а не старый дизайн в стиле WinForms. Посмотрите StackOverflow и другие ресурсы, чтобы узнать о MVVM. - person Ray Burns; 17.02.2010
comment
К вашему сведению: в целом Stack Overflow побуждает пользователей задавать дополнительные вопросы как новые, а не расширять существующие. См. FAQ и обсуждения на meta.stackoverflow.com для получения дополнительной информации. - person Ray Burns; 17.02.2010
comment
Круто, спасибо за исправление и указание на дизайн MVVM. - person Jeff Camera; 17.02.2010