Win8学习之 数据绑定
点击确定后,选择模拟器运行环境:
试试看你的应用程序是否能够正常运行,可以的话,继续下面的步骤。
开发之前我们先细想一下这个工程,要做的是要把课程的数据显示出来,那么就要用到数据绑定了。熟悉wp7和silverlight开发的朋友,接下来你就会发现,在win8(XAML+c#)开发当中,数据绑定是一样的。
首先,我们修改下我们的工程,新建一个命名为Resources.然后在 文件夹右键–添加–新建项,选取资源字典。命名为:MyDictionary.xaml。添加一行画刷来作为背景。并且修改代码如下:
1
2
3
4
5
6
7
8
9
10
11
|
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TimeTable.Resources">
<SolidColorBrush Color="#0099FF"x:Key="AppBackgroundColor"/>
</ResourceDictionary>
|
现在打开App.xaml。添加对MyDicitonary.xaml的声明。修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<ResourceDictionary.MergedDictionaries>
<!--
Styles that define common aspects of the platform look andfeel
Required by Visual Studio project anditem templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
<ResourceDictionary Source="Resources/MyDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
|
现在修改MainPage.xaml的grid的背景。
1
|
<Grid Background="{StaticResource AppBackgroundColor}">
|
现在,就能看到背景色变为了蓝色。接下来就进行数据定义吧。我们的数据类都继承INotifyPropertyChanged接口,以便数据更 新的时候能够自己通知控件更新。添加一个Data的文件夹。然后新建添加三个类,分别是 ViewModel.cs,WeekdayItem.cs,ScheduleItem.cs .
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
classViewModel:INotifyPropertyChanged
{
privateObservableCollection<WeekdayItem>weekdayList;
publicObservableCollection<WeekdayItem>WeekdayList{get{returnweekdayList;}}
privateintselectedItemIndex;
publicintSelectedItemIndex
{
get{returnselectedItemIndex;}
set{selectedItemIndex=value;NotifyPropertyChanged("SelectedItemIndex");}
}
publicViewModel()
{
weekdayList=newObservableCollection<WeekdayItem>();
selectedItemIndex=-1;
}
publicevent PropertyChangedEventHandler PropertyChanged;
privatevoidNotifyPropertyChanged(stringpropName)
{
if(PropertyChanged!=null)
{
PropertyChanged(this,newPropertyChangedEventArgs(propName));
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
classWeekdayItem:INotifyPropertyChanged
{
privateObservableCollection<ScheduleItem>scheduleList;
privateintscheduleSelected;
publicintScheduleSelected
{
get{returnscheduleSelected;}
set{scheduleSelected=value;NotifyPropertyChanged("ScheduleSelected");}
}
publicObservableCollection<ScheduleItem>ScheduleList
{
get{returnscheduleList;}
}
publicWeekdayItem()
{
scheduleList=newObservableCollection<ScheduleItem>();
weekday="Monday";
}
privatestringweekday;
publicstringWeekday
{
get{returnweekday; }
set{weekday=value;NotifyPropertyChanged("WeekDay");}
}
publicevent PropertyChangedEventHandler PropertyChanged;
privatevoidNotifyPropertyChanged(stringpropName)
{
if(PropertyChanged!=null)
{
PropertyChanged(this,newPropertyChangedEventArgs(propName));
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
classScheduleItem:INotifyPropertyChanged
{
privatestringlessonName;
publicstringLessonName
{
get{returnlessonName;}
set
{
lessonName=value;
NotifyPropertyChanged("LessonName");
}
}
privatestringstartTime;
publicstringStartTime
{
get
{
returnstartTime;
}
set
{
startTime=value;
NotifyPropertyChanged("StartTme");
}
}
privatestringendTime;
publicstringEndTime
{
get{returnendTime; }
set
{
endTime=value;
NotifyPropertyChanged("EndTime");
}
}
privatestringclassRoom;
publicstringClassRoom
{
get{returnclassRoom; }
set{classRoom=value;NotifyPropertyChanged("ClassRoom");}
}
publicevent PropertyChangedEventHandler PropertyChanged;
privatevoidNotifyPropertyChanged(stringpropName)
{
if(PropertyChanged!=null)
{
PropertyChanged(this,newPropertyChangedEventArgs(propName));
}
}
}
|
上面的代码已经很清楚了。就不多说了。
温馨提示:要用到InotifyPropertyChanged接口,必须先引用System.ComponentModel命名空间哦,还有动态 数据集合ObservableCollection也需要引用System.Collections.ObjectModel命名空间的哦,不然看到红色 下划波浪线还傻傻不知道什么事。还有一点需要说明的是,InotifyPropertyChanged接口在以前的开发中用的是 Windows.UI.Xaml.Data命名空间,在WinRT下变成了System.ComponentModel了,谨记!另外本教程涉及到文件夹 下的文件,命名空间不统一,如果你要在MainPage里调用Data文件夹里的文件,必须添加命名空间TimeTable.Data,下面将要建立的 Pages文件夹同理。
下面进行数据绑定。首先,在MyDictionary.xaml的SolidColorBrush的下面添加下面一段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<Stylex:Key="WeekdayListStyle"TargetType="TextBlock"BasedOn="{Binding BasicTextStyle}">
<Setter Property="FontSize"Value="45"/>
<Setter Property="FontWeight"Value="Light"/>
<Setter Property="Margin"Value="10,0"/>
<Setter Property="VerticalAlignment"Value="Center"/>
</Style>
<DataTemplatex:Key="WeekdayListItemTemplate">
<TextBlock Text="{Binding Weekday}"Style="{StaticResource WeekdayListStyle}"/>
</DataTemplate>
|
上面定义了一个数据模板,BasicTextStyle定义在Common/StandardStyles.xaml里面,这个文件里面定义了很多style。
下面修改MainPage的Grid。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<Grid Background="{StaticResource AppBackgroundColor}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.RowSpan="2">
<TextBlockx:Name="WeekdayListTitle"Style="{StaticResource HeaderTextStyle}"Margin="10"
Text="星期列表"/>
<ListViewx:Name="weekdayList" Grid.RowSpan="2"
ItemsSource="{Binding WeekdayList}"
ItemTemplate="{StaticResource WeekdayListItemTemplate}">
</ListView>
</StackPanel>
<StackPanel Orientation="Vertical"Grid.Column="1"Grid.RowSpan="2">
<TextBlock Style="{StaticResource HeaderTextStyle}"Margin="10"x:Name="ItemDetailTitle"
Text="课程细节"/>
<Framex:Name="ItemDetailFrame"/>
</StackPanel>
</Grid>
|
上面定义的style除了自己定义的,基本都是在Common/StandardStyles.xaml里面。熟悉数据绑定的能在上面的代码看 到熟悉的代码影吧。绑定了ListView的ItemsSource和ItemTemplate。下面的Frame标签以后再讲。
然后修改后台的构造函数和添加一个函数来往viewModel添加数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
ViewModel viewModel;
publicMainPage()
{
viewModel=newViewModel();
addData();
this.DataContext=viewModel;
this.InitializeComponent();
}
/// <summary>
/// 往viewModel添加数据
/// </summary>
privatevoidaddData()
{
WeekdayItem monday=newWeekdayItem();
monday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-215",
StartTime="8:30",
EndTime="10:00",
LessonName="数学"
});
monday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-216",
StartTime="10:30",
EndTime="12:00",
LessonName="物理"
});
monday.ScheduleList.Add(newScheduleItem
{
ClassRoom="E-303",
StartTime="14:30",
EndTime="16:00",
LessonName="计算机"
});
monday.Weekday="星期一";
viewModel.WeekdayList.Add(monday);
WeekdayItem tuesday=newWeekdayItem();
tuesday.Weekday="星期二";
tuesday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-215",
StartTime="8:30",
EndTime="10:00",
LessonName="数学"
});
tuesday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-216",
StartTime="10:30",
EndTime="12:00",
LessonName="物理"
});
tuesday.ScheduleList.Add(newScheduleItem
{
ClassRoom="E-303",
StartTime="14:30",
EndTime="16:00",
LessonName="英语"
});
viewModel.WeekdayList.Add(tuesday);
WeekdayItem wednesday=newWeekdayItem();
wednesday.Weekday="星期三";
wednesday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-215",
StartTime="8:30",
EndTime="10:00",
LessonName="数学"
});
wednesday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-216",
StartTime="10:30",
EndTime="12:00",
LessonName="物理"
});
wednesday.ScheduleList.Add(newScheduleItem
{
ClassRoom="E-303",
StartTime="14:30",
EndTime="16:00",
LessonName="英语"
});
viewModel.WeekdayList.Add(wednesday);
WeekdayItem thursday=newWeekdayItem();
thursday.Weekday="星期四";
thursday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-215",
StartTime="8:30",
EndTime="10:00",
LessonName="数学"
});
thursday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-216",
StartTime="10:30",
EndTime="12:00",
LessonName="物理"
});
thursday.ScheduleList.Add(newScheduleItem
{
ClassRoom="E-303",
StartTime="14:30",
EndTime="16:00",
LessonName="英语"
});
viewModel.WeekdayList.Add(thursday);
WeekdayItem friday=newWeekdayItem();
friday.Weekday="星期五";
friday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-215",
StartTime="8:30",
EndTime="10:00",
LessonName="数学"
});
friday.ScheduleList.Add(newScheduleItem
{
ClassRoom="B-216",
StartTime="10:30",
EndTime="12:00",
LessonName="物理"
});
friday.ScheduleList.Add(newScheduleItem
{
ClassRoom="E-303",
StartTime="14:30",
EndTime="16:00",
LessonName="英语"
});
viewModel.WeekdayList.Add(friday);
}
|
在构造函数,我们指定了当前页面的信息源DataContext为当前声明的viewModel。现在编译运行,就能看到运行结果如下:
下面我们要使用frame这个标签了。其实,每个页面都有这个Frame这个属性,这个Frame直接控制了导航,导航在Wp7里是用 navigationService来完成的。不过可能是由于平板的屏幕大,所以用这个Frame标签就可以做到局部导航。使之可以所有操作都在一个页面 完成。不过,如果开发者不实现导航返回按钮,win8平板就中间一个window键。如果能够返回上一层页面?至少我还没发现什么操作可以实现。
下面先给ListView添加一个SelectionChanged事件。当选项改变时触发。
1
2
3
4
5
|
privatevoidweekdayList_SelectionChanged_1(objectsender, SelectionChangedEventArgse)
{
viewModel.SelectedItemIndex=weekdayList.SelectedIndex;
}
|
只做了一件事,就是修改了viewModel的SelectedItemIndex的值。那么我们要注册一个PropertyChanged事件,监听当这个SelectedItemIndex改变的时候做相应的工作。
在Mainpage的构造函数最后添加:
|
上面我们监听了SelectedItemIndex。当改变的时候使ItemDetailFrame这个Frame导航到不同的页面。这个navigate方法,由VS2012的智能提示就知道,可以带参数,也可以不带参数。
下面我们新建一个文件夹Pages。然后添加一个空页面NoItemSelected.xaml。修改代码如下:
1
2
3
4
5
|
<Grid Background="{StaticResource AppBackgroundColor}">
<TextBlock Style="{StaticResource HeaderTextStyle}" FontSize="30"Text="No Item Selected"/>
</Grid>
|
然后再添加一个空白页ItemDetail.xaml到Pages文件夹。修改代码如下:
1
2
3
4
5
|
<Grid Background="{StaticResource AppBackgroundColor}">
<ListViewx:Name="ScheduleList"ItemsSource="{Binding ScheduleList}"IsHoldingEnabled="True"ItemTemplate="{StaticResource ScheduleListItemTemplate}"/>
</Grid>
|
然后修改ItemDetail页面的OnNavigateTo方法并添加一个变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
ViewModel viewModel;
protectedoverride voidOnNavigatedTo(NavigationEventArgse)
{
viewModel=e.Parameter asViewModel;
this.DataContext=viewModel.WeekdayList[viewModel.SelectedItemIndex];
viewModel.PropertyChanged+=(sender,args) =>
{
if(viewModel.SelectedItemIndex==-1)
{
this.DataContext=null;
}
else
this.DataContext=viewModel.WeekdayList[viewModel.SelectedItemIndex];
};
}
|
上面OnNavigateTo方法,在页面进入的时候,就获取页面传递过来的ViewModel这个数据。然后指定当前选择的Weekday为数据源。
上面我们还没定义ItemDetail页面ListView的数据模版。在MyDictionary.xaml添加如下模版:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<DataTemplatex:Key="ScheduleListItemTemplate">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding LessonName}"FontSize="30"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding StartTime}"FontSize="18"/>
<TextBlock Text="-"FontSize="18"/>
<TextBlock Text="{Binding EndTime}"FontSize="18"/>
</StackPanel>
<TextBlock Text="{Binding ClassRoom}"FontSize="30"/>
</StackPanel>
</DataTemplate>
|
这样,编译运行,就能看到选择左边的WeekdayList就能改变右边的ItemDetail部分了。