在WPF窗口的构造函数中,InitializeComponent()之前应该放什么?之后呢?

8
一般来说,在调用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构造函数中添加任何内容吗?

3个回答

6
通过在其他代码之后调用InitializeComponents,您可能会意外地覆盖在XAML中设置的属性,或者使用未初始化的对象。通常情况下,代码后台优先级高于XAML,因此我建议将InitializeComponents(也就是解析和加载XAML)放在顶部。

7
重要提示:如果使用MVVM,应在调用InitializeComponent()之前设置DataContext,否则您的ViewModel绑定将无法正确设置。InitializeComponent()会调用所有属性绑定getter,因此如果首先调用它,直到每个属性上再次调用NotifyPropertyChanged,您的绑定才能获得正确的值。对于任何可能影响xaml初始化方式的其他初始化逻辑,都适用同样的原则。 - jeff17237

4
回答您的具体问题:
你是否正在做一些可怕的事情?特别是在调用InitializeComponent()之前设置子控件的属性是否存在问题?
很有可能在调用InitializeComponent之前,您无法在代码中访问您的子控件。通常情况下,这样做是不好的做法。
在这方面,好的风格是什么?
这将是一个品味的问题,但我通常建议如果要利用XAML所提供的分离功能,则应该尽可能地分离。如果你正在做与UI逻辑相关的事情,请尝试在XAML中完成。这不仅仅是MVVM的事情,而是将表示与逻辑分开的基本原则。您在示例代码中的大部分工作都可以通过声明式方式完成,即使只是通过ValueConverters。
例如,如果Foo是一个DependencyProperty,则还可以在XAML中附加它并将回调添加为ValueChanged回调的一部分。同样,这不是MVVM,但它对于WPF来说非常基础。
对于大多数其他事情,您实际上可能希望等到OnLoaded被调用,而不是在构造函数中执行工作。
希望这可以帮助您,

我开始相信第一部分,但是有一个问题(正如在这个问题中提到的),OnLoaded被多次调用会有问题吗? - seeker
1
当您的控件被加载时,OnLoaded将被调用,这是挂接事件等操作的适当时间。您还需要在OnUnloaded中取消挂接它们。如果这是一个窗口,那么您实际上不应该看到OnLoaded被多次调用,但对于控件来说,这是一般需要小心的事情(链接的问题涉及页面,它们经常被加载/卸载)。 - Joe Castro
感谢您的详细回答。(很抱歉,我只能接受一个答案,而另一个回答先到了。) - seeker

2

在我调用InitializeComponent()之前,通常会把不需要可视树的所有内容称为“无需可视树的内容”。

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

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


这真的是一个问题吗?我的意思是,在我们调用Window.Show()之前,用户看不到控件,而这只会在构造函数完全退出后才会发生。我想对于一个“UserControl”来说可能更成问题,但即使是那样,对象被分配后应该已经完全构建好了。 - seeker

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