Как найти потомков элемента управления пользователя вместо окна - заменив Window.FindName - PullRequest
3 голосов
/ 18 ноября 2009

В настоящее время у меня есть проект WPF, который имеет одно главное окно и множество пользовательских элементов управления, которые являются дочерними элементами этого окна. Многие из детей этого окна являются вкладками. Я успешно заменил свое главное окно на пользовательский элемент управления, который реализует почти ту же функциональность, что и главное окно.

Замена окна на UserControl представила одну проблему - в настоящее время наше приложение определяет, какую вкладку программирования отображать на основе родительского окна, используя метод Window.FindName, показанный ниже. Поэтому мне нужно заменить Application.Current.MainWindow соответствующим описанием моего основного пользовательского элемента управления. См. Ошибочный метод C # ниже и wpf создание вкладок для пояснения.

Примечание относительно метода Window.FindName () - причина, по которой он не работает после того, как я заменил его на UserControl, заключается в том, что метод FindName осуществляет поиск вверх в визуальном дереве , как описано здесь .

Кто-нибудь знает, как найти пользовательский элемент управления на основе x: Name, похожий на Application.Current.MainWindow? Кроме того, есть ли лучший способ найти UserControl, чем поиск строки x: Name на случай, если она будет переименована?

Как мы в настоящее время находим MainWindow - теперь нужно найти MainUserControl:

(C#)
private static void SetCurrentProgram(int num)
    {
        Window window = Application.Current.MainWindow;
        ProgrammingTab programmingTab1 = window.FindName("ProgrammingTab1") as ProgrammingTab;
        ProgrammingTab programmingTab2 = window.FindName("ProgrammingTab2") as ProgrammingTab;

        programmingTab1.Visibility = num == 1 ? Visibility.Visible : Visibility.Collapsed;
        programmingTab2.Visibility = num == 2 ? Visibility.Visible : Visibility.Collapsed;

    }

Создание вкладок программирования.

(xaml)
<Grid>
 <ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab1" Program="1" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" />
 <ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab2" Program="2" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" />
</Grid>

Ответы [ 3 ]

2 голосов
/ 18 ноября 2009

Похоже, ваше приложение разработано в стиле WinForms. Чтобы придерживаться этого стиля и просто ответить на свой вопрос, вы можете найти FindName (), чтобы найти UserControl, и снова найти вкладку ProgrammingTab, например:

var userControl = (MyUserControl)Application.Current.MainWindow.FindName("userControlName");
var programmingTab1 = (ProgrammingTab)userControl.FindName("ProgrammingTab1");
var programmingTab2 = (ProgrammingTab)userControl.FindName("ProgrammingTab2");
...

Однако я бы порекомендовал вам изучить расширенные возможности WPF, такие как привязка данных. Вы можете иметь DependencyProperty "CurrentProgram" для одноэлементного объекта, на который ссылается статическое свойство, и просто привязать к нему Visiblity с помощью конвертера.

<ProgrammingTab Visibilty="{Binding CurrentProgram,
   Source={x:Static MyState.Instance},
   Converter={x:Static VisibleIfEqualConverter},
   ConverterParameter=1}" ...>
  ...

С этим изменением ваша SetCurrentProgram становится просто:

public void SetCurrentProgram(int num)
{
   MyState.Instance.CurrentProgram = num;
}

Прелесть этого метода в том, что любая ProgrammingTab в любом месте вашего приложения будет автоматически появляться или исчезать каждый раз, когда изменяется значение MyState.Instance.CurrentProgram, без необходимости искать их с помощью FindName () или другого.

0 голосов
/ 15 сентября 2010
0 голосов
/ 19 ноября 2009

Я нашел обходной путь для этой проблемы: я создал новый алгоритм, основанный на алгоритме другого пользователя StackOverflow, который рекурсивно находил любые дочерние объекты DependencyObject. Найдите мое решение здесь . Если вы объявите метод FindChild () в моем другом сообщении в public static class UIHelper {}, вы сможете решить проблему, выполнив следующее:

  ProgrammingTab programmingTab1 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab1");
  ProgrammingTab programmingTab2 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab2");

При этом все еще используется процедурный код вместо декларативного XAML для привязок, как предложил RayBurns. Если это сработает, его решение будет гораздо более эффективным, поскольку оно будет обходить не целое дерево, а просто изменять видимость вкладок на основе конвертера. Сейчас я протестирую это решение и посмотрю, как оно получится.

Причина, по которой FindName () не работает должным образом, описана в сообщении здесь .

...