win8学习之数据绑定

时间:2022-12-28 23:21:27

首先,打开VS2012,然后新建一个工程,命名为TimeTable。

  

 win8学习之数据绑定

 

  点击确定后,选择模拟器运行环境:

  

 win8学习之数据绑定

 

  试试看你的应用程序是否能够正常运行,可以的话,继续下面的步骤。

开发之前我们先细想一下这个工程,要做的是要把课程的数据显示出来,那么就要用到数据绑定了。熟悉wp7和silverlight开发的朋友,接下来你就会发现,在win8(XAML+c#)开发当中,数据绑定是一样的。

  首先,我们修改下我们的工程,新建一个命名为Resources.然后在 文件夹右键–添加–新建项,选取资源字典。命名为:MyDictionary.xaml。添加一行画刷来作为背景。并且修改代码如下:

1234567891011 <ResourceDictionary    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:TimeTable.Resources">    <SolidColorBrushColor="#0099FF"x:Key="AppBackgroundColor"/></ResourceDictionary>

  现在打开App.xaml。添加对MyDicitonary.xaml的声明。修改如下:

123456789101112131415 <ResourceDictionary.MergedDictionaries>                <!--                    Stylesthat define commonaspects of theplatform look andfeel                     Requiredby Visual Studioproject anditem templates                 -->                <ResourceDictionarySource="Common/StandardStyles.xaml"/>                <ResourceDictionarySource="Resources/MyDictionary.xaml"/>            </ResourceDictionary.MergedDictionaries>

  现在修改MainPage.xaml的grid的背景。

1 <GridBackground="{StaticResource AppBackgroundColor}">

  现在,就能看到背景色变为了蓝色。接下来就进行数据定义吧。我们的数据类都继承INotifyPropertyChanged接口,以便数据更新的时候能够自己通知控件更新。添加一个Data的文件夹。然后新建添加三个类,分别是ViewModel.cs,WeekdayItem.cs,ScheduleItem.cs .

  代码如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 classViewModel :INotifyPropertyChanged     {        privateObservableCollection<WeekdayItem>weekdayList;         publicObservableCollection<WeekdayItem>WeekdayList {get {return weekdayList;} }        privateint selectedItemIndex;        publicint SelectedItemIndex        {            get{ returnselectedItemIndex;}             set{ selectedItemIndex= value;NotifyPropertyChanged("SelectedItemIndex");}         }        publicViewModel()        {            weekdayList= newObservableCollection<WeekdayItem>();            selectedItemIndex= -1;        }        publicevent PropertyChangedEventHandler PropertyChanged;         privatevoid NotifyPropertyChanged(stringpropName)         {            if(PropertyChanged!= null)            {                PropertyChanged(this,new PropertyChangedEventArgs(propName));            }        }    }

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 classWeekdayItem :INotifyPropertyChanged     {        privateObservableCollection<ScheduleItem>scheduleList;         privateint scheduleSelected;        publicint ScheduleSelected        {            get{ returnscheduleSelected;}             set{ scheduleSelected= value;NotifyPropertyChanged("ScheduleSelected");}         }        publicObservableCollection<ScheduleItem>ScheduleList         {            get{ returnscheduleList;}         }        publicWeekdayItem()        {            scheduleList= newObservableCollection<ScheduleItem>();            weekday= "Monday";        }        privatestring weekday;        publicstring Weekday        {            get{ returnweekday; }             set{ weekday= value;NotifyPropertyChanged("WeekDay");}         }        publicevent PropertyChangedEventHandler PropertyChanged;         privatevoid NotifyPropertyChanged(stringpropName)         {            if(PropertyChanged!= null)            {                PropertyChanged(this,new PropertyChangedEventArgs(propName));            }        }    }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 classScheduleItem :INotifyPropertyChanged     {        privatestring lessonName;        publicstring LessonName        {            get{ returnlessonName;}             set            {                lessonName= value;                NotifyPropertyChanged("LessonName");            }        }        privatestring startTime;        publicstring StartTime        {            get            {                returnstartTime;             }            set            {                startTime= value;                NotifyPropertyChanged("StartTme");            }        }        privatestring endTime;        publicstring EndTime        {            get{ returnendTime; }             set            {                endTime= value;                NotifyPropertyChanged("EndTime");            }        }        privatestring classRoom;        publicstring ClassRoom        {            get{ returnclassRoom; }             set{ classRoom= value;NotifyPropertyChanged("ClassRoom");}         }        publicevent PropertyChangedEventHandler PropertyChanged;         privatevoid NotifyPropertyChanged(stringpropName)         {            if(PropertyChanged!= null)            {                PropertyChanged(this,new PropertyChangedEventArgs(propName));            }        }}

上面的代码已经很清楚了。就不多说了。

温馨提示:要用到InotifyPropertyChanged接口,必须先引用System.ComponentModel命名空间哦,还有动态数据集合ObservableCollection也需要引用System.Collections.ObjectModel命名空间的哦,不然看到红色下划波浪线还傻傻不知道什么事。还有一点需要说明的是,InotifyPropertyChanged接口在以前的开发中用的是Windows.UI.Xaml.Data命名空间,在WinRT下变成了System.ComponentModel了,谨记!另外本教程涉及到文件夹下的文件,命名空间不统一,如果你要在MainPage里调用Data文件夹里的文件,必须添加命名空间TimeTable.Data,下面将要建立的Pages文件夹同理。

  下面进行数据绑定。首先,在MyDictionary.xaml的SolidColorBrush的下面添加下面一段代码:

1234567891011121314151617 <Stylex:Key="WeekdayListStyle"TargetType="TextBlock"BasedOn="{Binding BasicTextStyle}">        <SetterProperty="FontSize"Value="45"/>        <SetterProperty="FontWeight"Value="Light"/>        <SetterProperty="Margin"Value="10,0"/>        <SetterProperty="VerticalAlignment"Value="Center"/>    </Style>    <DataTemplatex:Key="WeekdayListItemTemplate">        <TextBlockText="{Binding Weekday}"Style="{StaticResource WeekdayListStyle}"/>    </DataTemplate>

  上面定义了一个数据模板,BasicTextStyle定义在Common/StandardStyles.xaml里面,这个文件里面定义了很多style。

  下面修改MainPage的Grid。

123456789101112131415161718192021222324252627282930313233343536373839404142434445 <GridBackground="{StaticResource AppBackgroundColor}">        <Grid.ColumnDefinitions>            <ColumnDefinition/>            <ColumnDefinition/>        </Grid.ColumnDefinitions>        <Grid.RowDefinitions>            <RowDefinition/>            <RowDefinition/>        </Grid.RowDefinitions>        <StackPanelGrid.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>        <StackPanelOrientation="Vertical"Grid.Column="1"Grid.RowSpan="2">            <TextBlockStyle="{StaticResource HeaderTextStyle}"Margin="10"x:Name="ItemDetailTitle"                      Text="课程细节"/>            <Framex:Name="ItemDetailFrame"/>        </StackPanel>    </Grid>

  上面定义的style除了自己定义的,基本都是在Common/StandardStyles.xaml里面。熟悉数据绑定的能在上面的代码看到熟悉的代码影吧。绑定了ListView的ItemsSource和ItemTemplate。下面的Frame标签以后再讲。

  然后修改后台的构造函数和添加一个函数来往viewModel添加数据。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 ViewModel viewModel;         publicMainPage()        {            viewModel= newViewModel();            addData();            this.DataContext= viewModel;            this.InitializeComponent();        }        /// <summary>        /// 往viewModel添加数据        /// </summary>        privatevoid addData()        {            WeekdayItemmonday =new WeekdayItem();            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);            WeekdayItemtuesday =new WeekdayItem();            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);            WeekdayItemwednesday =new WeekdayItem();            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);            WeekdayItemthursday =new WeekdayItem();            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);            WeekdayItemfriday =new WeekdayItem();            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。现在编译运行,就能看到运行结果如下:

 win8学习之数据绑定

   下面我们要使用frame这个标签了。其实,每个页面都有这个Frame这个属性,这个Frame直接控制了导航,导航在Wp7里是用navigationService来完成的。不过可能是由于平板的屏幕大,所以用这个Frame标签就可以做到局部导航。使之可以所有操作都在一个页面完成。不过,如果开发者不实现导航返回按钮,win8平板就中间一个window键。如果能够返回上一层页面?至少我还没发现什么操作可以实现。

  下面先给ListView添加一个SelectionChanged事件。当选项改变时触发。

12345 privatevoid weekdayList_SelectionChanged_1(objectsender, SelectionChangedEventArgs e)        {            viewModel.SelectedItemIndex= weekdayList.SelectedIndex;        }

  只做了一件事,就是修改了viewModel的SelectedItemIndex的值。那么我们要注册一个PropertyChanged事件,监听当这个SelectedItemIndex改变的时候做相应的工作。

  在Mainpage的构造函数最后添加:

 

12345678910111213 viewModel.PropertyChanged+= (sender,args) =>{   if(args.PropertyName=="SelectedItemIndex")   {    if(viewModel.SelectedItemIndex== -1)    {      ItemDetailFrame.Navigate(typeof(NoItemSelected));    }    else    {      ItemDetailFrame.Navigate(typeof(ItemDetail),viewModel);    }  }};

 

  上面我们监听了SelectedItemIndex。当改变的时候使ItemDetailFrame这个Frame导航到不同的页面。这个navigate方法,由VS2012的智能提示就知道,可以带参数,也可以不带参数。

  下面我们新建一个文件夹Pages。然后添加一个空页面NoItemSelected.xaml。修改代码如下:

12345 <GridBackground="{StaticResource AppBackgroundColor}">    <TextBlockStyle="{StaticResource HeaderTextStyle}"        FontSize="30"Text="No Item Selected"/></Grid>

  然后再添加一个空白页ItemDetail.xaml到Pages文件夹。修改代码如下:

12345 <GridBackground="{StaticResource AppBackgroundColor}">  <ListViewx:Name="ScheduleList"ItemsSource="{Binding ScheduleList}"IsHoldingEnabled="True"ItemTemplate="{StaticResource ScheduleListItemTemplate}"/></Grid>

  然后修改ItemDetail页面的OnNavigateTo方法并添加一个变量。

1234567891011121314151617181920212223242526272829 ViewModel viewModel; protectedoverride voidOnNavigatedTo(NavigationEventArgse)         {            viewModel= e.Parameteras ViewModel;            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添加如下模版:

 

123456789101112131415161718192021 <DataTemplatex:Key="ScheduleListItemTemplate">        <StackPanelOrientation="Vertical">            <TextBlockText="{Binding LessonName}"FontSize="30"/>            <StackPanelOrientation="Horizontal">                <TextBlockText="{Binding StartTime}"FontSize="18"/>                <TextBlockText="-"FontSize="18"/>                <TextBlockText="{Binding EndTime}"FontSize="18"/>            </StackPanel>            <TextBlockText="{Binding ClassRoom}"FontSize="30"/>        </StackPanel>    </DataTemplate>

这样,编译运行,就能看到选择左边的WeekdayList就能改变右边的ItemDetail部分了。

 win8学习之数据绑定