【IT168技术文档】
1, 避免在逻辑中引用界面元素,别把后台数据强加给UI
一个糟糕的案例
比如说主界面上有一个显示当前任务状态的标签label_TaskState,我们会时常更新该标签以便及时地将任务状态通知用户。那么很糟糕的一种假设是我们的代码中会到处充斥着这样的语句段this.label_TaskState .Content = this.GetStateDescription(TaskStates.Busy);(GetStateDescription方法会返回一段比较友好的描述信息)
当用户点击“暂停”按钮后,我们可能要这样来这样更新标签:
当由于某种原因我们的任务发生了错误时,我们可能会这样:void btn_Pause_Clicked(object sender, RoutedEventArgs e) { //do something to pause the task //update our lab this.label_TaskState .Content = this.GetStateDescription(TaskStates.Pause); }
这样一来,我们的逻辑代码无数地方将引用label_TaskState这个UI元素。try { //do something dangerous } catch(MyException e) { this.label_TaskState .Content = this.GetStateDescription(TaskStates.Error); } finally { //… }
现在有一些变化来了:(1)我们觉得使用一段文本来描述任务状态还是不够直观,所以我们决定使用美工提供的一系列漂亮图标来显示当前状态(图标中也可能含有文字,不过我们不关心)。(2)另外一个面板上(myPanel2)也要放置一个显示任务当前任务状态的标签label_TaskState2,只不过其仅仅显示文字描述就可以了。
那么我们在这么糟糕的环境下是不是应该像这样来修改我们的代码呢?
首先找出所有引用了label_TaskState的地方(比如有20个)。
然后将Lable类型的label_TaskState控件修改为Image类型的image_TaskState控件。
然后重复地将this.label_TaskState .Content = this.GetStateDescription(TaskStates.Busy);语句替换为this.image_TaskState.Source = this.GetStateImage(TaskStates.Busy);
别忘了每次都要在该语句后追加一条:this.label_TaskState2.Content = this.GetStateDescription(TaskStates.Busy);因为我们增加了一个标签。
多么令人上火的编程工作啊。
原因是,我们频繁地引用不稳定的界面元素(label_TaskState),严重地将界面和逻辑耦合在了一起,我们采用赋值的方式将后台数据(当前状态信息)强加给了UI元素。
解决方案:使用Binding,然UI元素从后台“拿”数据
一个简单的描述是:后台逻辑对前台UI说“要如何展现由前台决定,数据就在这里,要用就自己来拿吧”
“数据就在这里”
我们的数据是当前任务的状态信息,为了提供给UI元素和后台逻辑使用,我们决定提供一个TheTaskState属性来跟踪当前状态:
public TaskStates TheTaskState { get { return (TaskStates)GetValue(TheTaskStateProperty); } set { SetValue(TheTaskStateProperty, value); } } public static readonly DependencyProperty TheTaskStateProperty = DependencyProperty.Register("TheTaskState", typeof(TaskStates), typeof(Window1), new UIPropertyMetadata(TaskStates.Idle));