3

我目前有一个 WPF 项目,它有一个主窗口和许多用户控件,它们是这个窗口的子窗口。此窗口的许多子项都是选项卡。我已经成功地用一个用户控件替换了我的主窗口,它实现了与主窗口几乎完全相同的功能。

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

注意关于 Window.FindName() 方法- 我用 UserControl 替换它后它不起作用的原因是 FindName 方法在可视树中向上搜索,如此处所述

有谁知道如何根据 x:Name 找到用户控件,类似于Application.Current.MainWindow?此外,有没有比查找 x:Name 字符串更好的方法来查找 UserControl,以防它被重命名?

我们目前如何找到 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>
4

3 回答 3

3

听起来您的应用程序是以非常类似于 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() 或其他方式找到它们。

于 2009-11-18T20:27:31.133 回答
0

我想出了一个解决这个问题的方法:我基于另一个 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");

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

FindName() 无法正常工作的原因在此处的帖子中进行了描述。

于 2009-11-19T15:27:07.810 回答
0

这篇文章可以帮助你:http ://blog.lexique-du-net.com/index.php?post/2010/09/14/UserControl/Control-how-to-get-a-reference-to-an-模板元素

于 2010-09-15T09:10:10.213 回答