问题:在某些情况下,WPF中的自定义用户控件中的LOADED事件会执行两次,典型问题是在TabControl中动态加入TabItem,再加入UserControl,比如代码如下:
UserControl1 uc = new UserControl1(); TabItem tab = new TabItem(); tab.Header = "test"; tab.Content = uc; this.tabControl.Items.Add(tab);
此时,如果在UserControl1中的Loaded事件中加入Message测试,则在创建时引发一次,而在Focus时又引发一次,这个也可以说不是一个Bug,因为每次Focus时都会引发此事件。但问题是,当遇见如下代码,则会引起一个很奇怪的错误:
public partial class UserControl1 : UserControl { public Test test = null; public UserControl1() { InitializeComponent(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { if (test == null) { test = new Test(); //test.testString = "testString"; } else { test = null; } this.DataContext = test; //this.grd.ItemsSource = test.testList; MessageBox.Show("Proc"); } private void button_Click(object sender, RoutedEventArgs e) { if (test == null) { MessageBox.Show("null"); } else { MessageBox.Show(test.testString); } } } public class Test { public string testString = null; public List<string> testList = null; }
注意:在Click事件中,test为Null。
当然没有人会这样写代码,但是在一些应用中,比如数据库应用,这样的代码会非常的容易出现,比如:
if (test == null) { test = new Test(); //test.testString = "testString"; } else { //加载数据,test可能为null test = DB.SameTable.SingleOrDefault......... } this.DataContext = test; //this.grd.ItemsSource = test.testList; MessageBox.Show("Proc"); }
此时,(由于编译器版本不同原因,不同的的版本会得到不同的test,有的版本为null,有的版本为非null,依据是否执行两次Loaded事件而定,测试环境:VS2015),在Loaded事件中所写的代码,可能会有不同的表现,所以得出最后结论:Loaded事件,能不用则不用。