什么是在WPF窗口和其用户控件之间共享数据的最佳方法?

7

有时候WPF会让人很恼火。

我有一个相当简单的应用程序,它由一个包含选项卡控件和几个选项卡的主窗口组成。我不喜欢在同一个文件中编写所有选项卡的代码,因此我使用了这个问题的答案,将每个选项卡拆分为单独的用户控件。

在我的主窗口中,我有一个包含应用程序设置和其他应用程序范围数据的对象实例。我的一些选项卡需要访问此数据以进行数据绑定。我一直没有找到一个好的方法来实现这一点。

首先,我尝试在控件的Loaded事件中访问父窗口,并获取主窗口中公开设置对象属性的引用,如下面的代码所示。这种方法有点可行,但是Loaded事件在每次选项卡获得焦点时都会触发。此外,该事件发生在控件生命周期的晚期,因此我无法在用户控件的XAML中绑定该对象的任何属性。

private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
{
    this.ApplicationSettings = ((MainWindow)Window.GetWindow(this)).ApplicationSettings;
}

我尝试将数据传递到用户控件的构造函数中,但是在XAML中没有办法这样做。

考虑到这些是应用程序范围内的设置,我可以将ApplicationSettings类作为单例并在所有地方引用它,但出于单元测试目的,我不想这样做。

那么如何实现这样的操作呢?我的方法是否根本存在缺陷?在我看来,所有这些UI元素都是同一个窗口的一部分,因此应该能够访问主窗口中的数据,但是对象模型似乎不允许这样做。

3个回答

2
在您的用户控件声明中,您可以将数据上下文设置为包含所有需要绑定的内容的对象的实例! <someNamespace:EricsUserControl DataContext="{Binding InstanceOfBindingObject}"/>
然后,您可以像通常一样在用户控件内访问该对象实例的属性。

这真的很好知道,我可能会在其他方面使用它,但我也想保留在代码中访问设置的选项。 - EricTheRed
@EricTheRed 完全合理,但是提醒一下,你也可以在代码中访问用户控件的 DataContext。因此,如果你像上面那样绑定到实例对象,然后在代码后台文件中执行一些小操作 var myInstance = (BindingObjectClass) this.DataContext,你就可以从 myInstance 变量中访问该对象!希望这能在将来的某个时候有所帮助! - Kevek

2
你可以将设置对象放入一个包装类的静态属性中(在此示例中为SettingsHolder),并通过以下方式在整个应用程序中引用它:

在XAML中:

{Binding SettingName, Source={x:Static local:SettingsHolder.Settings}}

假设您的SettingsHolder类位于local命名空间中。

在代码中:

var x = SettingsHolder.Settings.SettingName;
SettingsHolder.Settings.SettingName = x;

我认为这是我要走的路线。就像我在原始帖子中所说的,我想要单例行为而不需要实际的单例,这个方案可以满足我的需求。实际上,我可能会使这个类成为单例,但保留公共构造函数用于测试目的。 - EricTheRed

0
我所做的是在选项卡中使用一个Frame,并在Frame中放置一个Page(但我认为同样适用于用户控件)。只有在创建页面时构造函数才会触发,您可以控制何时创建页面并可以通过构造函数传递信息。页面具有更多的生命周期事件可供使用。我还使用Loaded事件来构建UI(它只会触发一次)。如果在XAML中绑定页面,它将在启动应用程序时触发,您无法传递信息。这将创建一个页面并在对话框中显示它,但该页面可以绑定到一个框架上。
        NavigationWindow winSearchXML;
        using (new WaitCursor())
        {
            winSearchXML = new NavigationWindow();
            winSearchXML.Content = new PageSearchResultsXML(GabeLib.GetSearchXML(GabeLib.enumXMLtype.Flat));
        }
        winSearchXML.ShowDialog();

说实话,有时候我会遇到一些页面的生命周期我并不理解。所以请谨慎对待我的建议。但是重点是你可以通过构造函数和加载事件来获取你需要的信息。


太聪明了!我从没想过做这样的事情。不过,我认为对于我正在处理的项目来说,这有点过度设计了。不过还是谢谢你提供的思路。 - EricTheRed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接