请考虑以下代码:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Slider ValueChanged="slider_ValueChanged/>
<TextBox x:Name="counter"/>
</StackPanel>
</Window>
和
namespace Project1
{
public partial class Window1 : Window
{
public MainWindow() { InitializeComponent(); }
void slider_ValueChanged(object sender,
RoutedPropertyChangedEventArgs<double> e)
{
counter.Text = e.NewValue.ToString();
}
}
}
当ValueChanged
仍为counter
时,幻灯片会在初始化期间提升其null
事件。
这是我使用WPF遇到的一个更大问题的一个例子,UI事件可以随时触发,而且没有一个地方可以放置我的初始化代码,以确保它能够运行在WPF系统拥有的所有指针都已初始化之后但在任何UI事件被触发之前。
处理这个问题最优雅的方法是什么?这个具体的例子应该使用数据绑定的事实不是重点。
答案 0 :(得分:3)
根据您的具体情况,有很多方法可以解决这个问题
首先,你可以简单地认识到对象可能没有被初始化并在处理之前检查它。例如,
if (counter.Text != null)
counter.Text = e.NewValue.ToString();
其次,您可以将事件附加到对象的Loaded事件中,这样它们就不会在对象初始化之后才会触发。
void Counter_Loaded(object sender, EventArgs e)
{
slider.ValueChanged += Slider_ValueChanged;
}
void Counter_Unloaded(object sender, EventArgs e)
{
slider.ValueChanged -= Slider_ValueChanged;
}
最后,您可以使用WPF的Dispatcher在不同DispatcherPriority的UI线程上运行事件。默认值为Normal
,在Loaded
,Render
和DataBind
操作后运行
Dispatcher.BeginInvoke(DispatcherPriority.DataBind,
new Action(delegate() { counter.Text = e.NewValue.ToString(); }));
答案 1 :(得分:2)
此问题的 true 答案是使用MVVM模式,其中文件后面的窗口代码几乎没有初始化代码。
在此模式中,UI仅与数据绑定连接到其余代码。您编写了实现INotifyPropertyChanged
的特殊视图模型类,并将您的业务逻辑公开,并将其作为UI绑定的一系列属性公开。
当然,您可以完全控制视图模型的初始化方式。