(二)實例講解win8(XAML+C#)開發--------課程表:數據綁定

免責聲明:本文章由fengyun1989創作,採用知識共享署名-非商業性使用-相同方式共享 2.5 中國大陸許可協議進行許可。

  首先,打開VS2012,然後新建一個工程,命名爲TimeTable

點擊確定後,看到編譯器如下地方:

現在空的工程也可以運行,選擇Simulator就是模擬器運行,選擇本地計算機就是直接在本機運行。現在就可以運行看看,就是黑屏。

在本機運行的話,如果想退出程序,可以把光標放到左上角,等待出現桌面縮略圖就點擊,這樣就能退出了。

數據綁定

  細想下這個工程,首先要做的是要把課程的數據顯示出來,那麼,就要用到數據綁定了。熟悉wp7和silverlight開發的朋友,接下來你就會發現,在win8(XAML+c#)開發當中,數據綁定是一樣的。

  首先,我們修改下我們的工程,新建一個命名爲Resources.然後在 文件夾右鍵--添加--新建項,選取資源字典。命名爲:MyDictionary.xaml。添加一行畫刷來作爲背景。並且修改代碼如下:

<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="#3E790A" x:Key="AppBackgroundColor"/>
</ResourceDictionary>
現在打開App.xaml。添加對MyDicitonary.xaml的聲明。修改如下:

<ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel
                    Required by Visual Studio project and item templates
                 -->
                <ResourceDictionary Source="Common/StandardStyles.xaml"/>
                <ResourceDictionary Source="Resources/MyDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>

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

<Grid Background="{StaticResource AppBackgroundColor}">

現在,就能看到背景色變爲了深綠色。接下來就進行數據定義吧。我們的數據類都繼承INotifyPropertyChanged接口,以便數據更新的時候能夠自己通知控件更新。添加一個Data的文件夾。然後新建添加三個類,分別是ViewModel.cs,WeekdayItem.cs,ScheduleItem.cs .類圖如下:

代碼如下:

class ViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<WeekdayItem> weekdayList;
        public ObservableCollection<WeekdayItem> WeekdayList { get { return weekdayList; } }
        private int selectedItemIndex;
        public int SelectedItemIndex
        {
            get { return selectedItemIndex; }
            set { selectedItemIndex = value; NotifyPropertyChanged("SelectedItemIndex"); }
        }

        public ViewModel()
        {
            weekdayList = new ObservableCollection<WeekdayItem>();
            selectedItemIndex = -1;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }

class WeekdayItem : INotifyPropertyChanged
    {
        private ObservableCollection<ScheduleItem> scheduleList;
        private int scheduleSelected;
        public int ScheduleSelected
        {
            get { return scheduleSelected; }
            set { scheduleSelected = value; NotifyPropertyChanged("ScheduleSelected"); }
        }
        public ObservableCollection<ScheduleItem> ScheduleList
        {
            get { return scheduleList; }
        }
        public WeekdayItem()
        {
            scheduleList = new ObservableCollection<ScheduleItem>();
            weekday = "Monday";
        }
        private string weekday;
        public string Weekday
        {
            get { return weekday; }
            set { weekday = value; NotifyPropertyChanged("WeekDay"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }

class ScheduleItem : INotifyPropertyChanged
    {
        private string lessonName;
        public string LessonName
        {
            get { return lessonName; }
            set
            {
                lessonName = value;
                NotifyPropertyChanged("LessonName");
            }
        }
        private string startTime;
        public string StartTime
        {
            get
            {
                return startTime;
            }
            set
            {
                startTime = value;
                NotifyPropertyChanged("StartTme");
            }
        }

        private string endTime;
        public string EndTime
        {
            get { return endTime; }
            set
            {
                endTime = value;
                NotifyPropertyChanged("EndTime");
            }
        }

        private string classRoom;
        public string ClassRoom
        {
            get { return classRoom; }
            set { classRoom = value; NotifyPropertyChanged("ClassRoom"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }

上面的代碼已經很清楚了。就不多說了。

下面進行數據綁定。首先,在MyDictionary.xaml的SolidColorBrush的下面添加下面一段代碼:

<Style x: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>
    <DataTemplate x:Key="WeekdayListItemTemplate">
        <TextBlock Text="{Binding Weekday}" Style="{StaticResource WeekdayListStyle}"/>
    </DataTemplate>

上面定義了一個數據模板,BasicTextStyle定義在Common/StandardStyles.xaml裏面,這個文件裏面定義了很多style。

下面修改MainPage的Grid。

<Grid Background="{StaticResource AppBackgroundColor}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Grid.RowSpan="2">
            <TextBlock x:Name="WeekdayListTitle" Style="{StaticResource HeaderTextStyle}" Margin="10"
                       Text="Weekday List"/>
            <ListView x: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="Schedule Detail"/>
            <Frame x:Name="ItemDetailFrame"/>
        </StackPanel> 
    </Grid>

上面定義的style除了自己定義的,基本都是在Common/StandardStyles.xaml裏面。熟悉數據綁定的能在上面的代碼看到熟悉的代碼影吧。綁定了ListView的ItemsSource和ItemTemplate。下面的Frame標籤以後再講。

然後修改後臺的構造函數和添加一個函數來往viewModel添加數據。

ViewModel viewModel;
        public MainPage()
        {
            viewModel = new ViewModel();
            addData();
            this.DataContext = viewModel;
            this.InitializeComponent();
        }

        /// <summary>
        /// 往viewModel添加數據
        /// </summary>
        private void addData()
        {
            WeekdayItem monday = new WeekdayItem();
            monday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-215",
                StartTime = "8:30",
                EndTime = "10:00",
                LessonName = "Math"
            });
            monday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-216",
                StartTime = "10:30",
                EndTime = "12:00",
                LessonName = "Physic"
            });
            monday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "E-303",
                StartTime = "14:30",
                EndTime = "16:00",
                LessonName = "Computer"
            });
            monday.Weekday = "星期一";
            viewModel.WeekdayList.Add(monday);
            WeekdayItem tuesday = new WeekdayItem();
            tuesday.Weekday = "星期二";
            tuesday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-215",
                StartTime = "8:30",
                EndTime = "10:00",
                LessonName = "Math"
            });
            tuesday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-216",
                StartTime = "10:30",
                EndTime = "12:00",
                LessonName = "Physic"
            });
            tuesday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "E-303",
                StartTime = "14:30",
                EndTime = "16:00",
                LessonName = "English"
            });
            viewModel.WeekdayList.Add(tuesday);

            WeekdayItem wednesday = new WeekdayItem();
            wednesday.Weekday = "星期三";
            wednesday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-215",
                StartTime = "8:30",
                EndTime = "10:00",
                LessonName = "數學"
            });
            wednesday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-216",
                StartTime = "10:30",
                EndTime = "12:00",
                LessonName = "Physic"
            });
            wednesday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "E-303",
                StartTime = "14:30",
                EndTime = "16:00",
                LessonName = "English"
            });
            viewModel.WeekdayList.Add(wednesday);
            WeekdayItem thursday = new WeekdayItem();
            thursday.Weekday = "星期四";
            thursday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-215",
                StartTime = "8:30",
                EndTime = "10:00",
                LessonName = "數學"
            });
            thursday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-216",
                StartTime = "10:30",
                EndTime = "12:00",
                LessonName = "Physic"
            });
            thursday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "E-303",
                StartTime = "14:30",
                EndTime = "16:00",
                LessonName = "English"
            });
            viewModel.WeekdayList.Add(thursday);
            WeekdayItem friday = new WeekdayItem();
            friday.Weekday = "星期五";
            friday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-215",
                StartTime = "8:30",
                EndTime = "10:00",
                LessonName = "數學"
            });
            friday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "B-216",
                StartTime = "10:30",
                EndTime = "12:00",
                LessonName = "Physic"
            });
            friday.ScheduleList.Add(new ScheduleItem
            {
                ClassRoom = "E-303",
                StartTime = "14:30",
                EndTime = "16:00",
                LessonName = "English"
            });
            viewModel.WeekdayList.Add(friday);

        }

在構造函數,我們指定了當前頁面的信息源DataContext爲當前聲明的viewModel。現在編譯運行,就能看到運行結果如下:

  下面我們要使用frame這個標籤了。其實,每個頁面都有這個Frame這個屬性,這個Frame直接控制了導航,導航在Wp7裏是用navigationService來完成的。不過可能是由於平板的屏幕大,所以用這個Frame標籤就可以做到局部導航。使之可以所有操作都在一個頁面完成。不過,如果開發者不實現導航返回按鈕,win8平板就中間一個window鍵。如果能夠返回上一層頁面?至少我還沒發現什麼操作可以實現。

  下面先給ListView添加一個SelectionChanged事件。當選項改變時觸發。

        private void weekdayList_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {
            viewModel.SelectedItemIndex = weekdayList.SelectedIndex;
        }

只做了一件事,就是修改了viewModel的SelectedItemIndex的值。那麼我們要註冊一個PropertyChanged事件,監聽當這個SelectedItemIndex改變的時候做相應的工作。

在Mainpage的構造函數最後添加:

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。修改代碼如下:

<Grid Background="{StaticResource AppBackgroundColor}">
        <TextBlock Style="{StaticResource HeaderTextStyle}"
                   FontSize="30" Text="No Item Selected"/>
    </Grid>

然後再添加一個空白頁ItemDetail.xaml到Pages文件夾。修改代碼如下:

<Grid Background="{StaticResource AppBackgroundColor}">
        <ListView x:Name="ScheduleList" ItemsSource="{Binding ScheduleList}"    
                  IsHoldingEnabled="True"   
                  ItemTemplate="{StaticResource ScheduleListItemTemplate}"/>
    </Grid>

然後修改ItemDetail頁面的OnNavigateTo方法並添加一個變量。

ViewModel viewModel;
protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            viewModel = e.Parameter as 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添加如下模版:

<DataTemplate x: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部分了。到此,數據綁定部分基本就這樣吧。還有部分彈出窗口的數據綁定到後面再說。

繼續學習:<win8>(三)實例講解win8(XAML+C#)開發--------課程表:彈出菜單ContextMenu和彈窗Flyout

本次工程下載:http://dl.dbank.com/c0eh4b1z85



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章