如何找到UserControl的子节点而不是窗口 - 替换Window.FindName

时间:2009-11-18 19:38:02

标签: c# wpf user-controls mainwindow findname

我目前有一个WPF项目,它有一个主窗口,以及许多UserControls,它们都是这个Window的子项。这个窗口的许多孩子都是Tabs。我已成功用一个用户控件替换了我的主窗口,该控件实现了与主窗口几乎完全相同的功能。

用UserControl替换Window引入了一个问题 - 目前我们的应用程序通过使用下面显示的Window.FindName方法确定基于父窗口显示哪个编程选项卡。因此,我需要用我的主要用户控件的适当描述替换Application.Current.MainWindow。请参阅下面的错误C#方法和选项卡的wpf实例化以获得说明。

注意关于Window.FindName()方法 - 在我用UserControl替换它之后它不起作用的原因是因为FindName方法在可视树中向上搜索as described here

有没有人知道如何根据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 个答案:

答案 0 :(得分:2)

听起来您的应用程序是以类似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;
}

这种技术的优点在于,每当MyState.Instance.CurrentProgram的值发生变化时,应用程序中任何位置的任何ProgrammingTab都会自动显示或消失,而无需使用FindName()或其他方式找到它们。

答案 1 :(得分:0)

我找到了解决这个问题的方法:我基于另一个StackOverflow用户的算法创建了一个新算法,该算法递归地找到了DependencyObject的任何子项。查找my solution here。如果您在public static class UIHelper {}中的其他帖子中声明FindChild()方法,则可以通过执行以下操作来解决问题:

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

这仍然使用过程代码而不是声明性XAML来进行像RayBurns建议的绑定。如果它工作,他的解决方案将更有效,因为它不会遍历整个树,而只是改变基于转换器的选项卡的可见性。我现在将测试该解决方案,看看结果如何。

post here中描述了FindName()无法正常工作的原因。

答案 2 :(得分:0)