【问题标题】:In a constructor for a WPF Window, what should go before InitializeComponent() and what after?在 WPF 窗口的构造函数中,InitializeComponent() 之前应该做什么,之后应该做什么?
【发布时间】:2012-07-13 22:47:22
【问题描述】:

一般来说,我在InitializeComponent() 之前初始化了Window 本身的属性,然后设置了其中包含的控件。但是,我并没有那么一致,我也没有真正注意到排序有问题。所以:

  • 我(可能)在做一些可怕的事情吗?特别是InitializeComponent()之前设置子控件的属性有什么问题吗?
  • 在这方面有什么好的风格?

编辑:由于我得到的前两个答案有点矛盾,让我更具体一点:

public Foo Foo {get; protected set}
public FooWindow (Foo foo)
{
    Foo = foo;
    this.Closing += FooWindow_Closing;
    Foo.Frobbed += Foo_Frobbed;

    InitializeComponent();

    this.DataContext = this;
    this.Title = Foo.Name() + " Window";

    FooListView.ItemSource = Foo.CalculateList();

    FocusManager.SetFocusedElement(this, FooListView);
}

这是对的吗?我应该只做 MVVM 而我的 Window 构造函数中没有任何东西吗?

【问题讨论】:

    标签: wpf coding-style


    【解决方案1】:

    通过在其他代码之后调用 InitializeComponents,您可能会冒着意外用 XAML 中设置的内容覆盖属性或使用未初始化对象的风险。通常,代码隐藏的优先级高于 XAML,因此我会将 InitializeComponents(也称为解析和加载 XAML)留在顶部。

    【讨论】:

    • 重要的是要注意,如果使用 MVVM,DataContext 应该在 调用 InitializeComponent() 之前设置,否则您的 ViewModel 绑定将无法正确设置。 InitializeComponent() 调用您所有的属性绑定 getter,因此如果首先调用它,您的绑定将不会获得正确的值,直到在您的每个属性上再次调用 NotifyPropertyChanged。同样的原则适用于可能影响您的 xaml 初始化方式的任何其他初始化逻辑。
    【解决方案2】:

    回答您的具体问题:

    我(可能)在做一些可怕的事情吗?特别是在 InitializeComponent() 之前设置子控件的属性有什么问题吗?

    在您调用 InitializeComponents 之前,您可能无法在代码中使用您的子控件。这样做通常是不好的形式。

    在这方面有什么好的风格?

    这将是一个品味问题,但通常我会建议,如果您要利用 XAML 为您提供的分离,那么我会尽可能地采用它。如果您正在做与 UI 相关的逻辑操作,请尝试在 XAML 中进行。这与其说是 MVVM 的事情,不如说是表示与逻辑的分离。示例代码中的大部分内容都可以通过声明方式完成,即使只是通过 ValueConverters。

    例如,如果 Foo 是一个 DependencyProperty,那么您也可以将它附加到 XAML 中并将回调添加为 ValueChanged 回调的一部分。同样,这不是 MVVM,但它是 WPF 的基础。

    对于大多数其他事情,您实际上可能希望等到 OnLoaded 被调用,而不是在构造函数中完成工作。

    希望对你有帮助,

    【讨论】:

    • 我开始相信第一部分,但是 OnLoaded 被多次调用是否存在问题(如this question 中所述)?
    • OnLoaded 将在您的控件加载时被调用,这是挂钩事件等的适当时间。您还需要在 OnUnloaded 中解开它们。如果这是一个窗口,那么你真的应该永远不会看到 OnLoaded 被多次调用,但是对于控件来说通常要小心(链接的问题是指经常加载/卸载的页面)。
    • 感谢您提供的信息丰富的回答。 (对不起,我只能接受一个答案,另一个是第一个。)
    【解决方案3】:

    我通常在调用 InitializeComponent() 之前调用任何不需要 Visual Tree 的东西。

    我的所有实现都使用 MVVM 模式,因此我更喜欢在 UI 加载到客户端之前实例化并填充我的 ViewModel。

    如果您总是先加载 InitializeComponent(),您会冒着创建糟糕的用户体验的风险,因为它会显示一个突然更新的未填充视图,而不是在它进入视图时填充的视图。 p>

    【讨论】:

    • 这真的有问题吗?我的意思是,在我们调用Window.Show() 之前,用户看不到控件,这在构造函数完全退出之前不会发生。我想这对于UserControl 来说可能是一个更大的问题,但即便如此,该对象应该在分配时完全构建。
    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    相关资源
    最近更新 更多