<win8>(三)实例讲解win8(XAML+C#)开发--------课程表:弹出菜单ContextMenu和弹窗Flyout
免责声明:本文章由fengyun1989创作,采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
友情提示下:win8下,输入法切换是window键+空格键。
下面我们来做的是一个弹窗来修改课程表里面的数据。那么我们用一个弹窗来实现数据的修改。那么用什么方式控制弹窗呢,用一个AppBar的按钮?我觉得还是在页面点击弹出比较好,我想用listView的某个事件来实现弹窗,但是我对win8里面的ListView的事件不太熟悉,查文档?我比较懒,懒得查文档也有两种方式,一种用智能提示,一种用属性页面的事件页。
从智能提示看到,可以选择的事件挺多的,我就选择DoubleTap.那么在ItemDetail页面添加一个DoubleTap事件:
<ListView x:Name="ScheduleList" ItemsSource="{Binding ScheduleList}" DoubleTapped="ScheduleList_DoubleTapped_1" ItemTemplate="{StaticResource ScheduleListItemTemplate}" />
那么我们在DoubleTap事件中实现弹出菜单。这里就先给出微软官方的ContextMenu的例子:http://code.msdn.microsoft.com/windowsapps/Context-menu-sample-40840351
ContextMenu有两种,一种是普通就弹出菜单,一种是选择文本后的弹出菜单。这里就用第一种,后一种是可以在选择文本后弹出菜单显示复制,粘贴等。后一种可以在微软给出的例子的Scenario2页面看到。
修改DoubleTap事件如下:
private async void ScheduleList_DoubleTapped_1(object sender, DoubleTappedRoutedEventArgs e) { if (ScheduleList.SelectedIndex != -1) { var menu = new PopupMenu(); menu.Commands.Add(new UICommand("Edit", (command) => { })); menu.Commands.Add(new UICommand("Delete", (command) => { })); await menu.ShowAsync(e.GetPosition(null)); } }
注意,这里的方法要修改为异步的,async和await这两个配合,await这个关键字,在win8才有,从字面文字就知道,就是等待后面的完成。用了await方法修饰,后面跟的要是异步的方法,整个方法也要用async修饰成异步的方法。关于await,推荐看:深入探究 WinRT 和 await
现在运行,在ListView上双击,就可以看到弹窗了。
接下来,我们做一个弹窗来修改数据。那么,用什么样的形式弹窗呢,在Wp7,我们可以用Canvas自定义弹窗,也有不少的第三方插件可以做到。当然,这里我们也可由用Canvas来自定义弹窗,不过这里我不打算这么做,我打算用win8有的一个弹窗Popup来实现。那么现在新建添加一个用户控件到Pages文件夹命名为EditItemFlyout.xaml。
去除原来的Grid修改代码如下:
<Popup x:Name="EditItemPopup" IsLightDismissEnabled="True" Width="435" Height="500"> <StackPanel Background="Black"> <Border Background="#85c54C" BorderThickness="4"> <Grid Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock Text="LessonName:" Grid.Column="0" Grid.Row="0" FontSize="24"/> <TextBox x:Name="Lessonname" Width="200" Height="40" Grid.Column="1" Grid.Row="0" Text="{Binding LessonName}" FontSize="24"/> <TextBlock Text="ClassRoom:" Grid.Column="0" Grid.Row="1" FontSize="24"/> <TextBox x:Name="Classroom" Grid.Column="1" Grid.Row="1" Width="200" Height="40" Text="{Binding ClassRoom}" FontSize="24"/> <TextBlock Text="StartTime:" Grid.Column="0" Grid.Row="2" FontSize="24" /> <TextBox x:Name="Starttime" Grid.Column="1" Grid.Row="2" Width="200" Height="40" Text="{Binding StartTime}" FontSize="24"/> <TextBlock Text="EndTime:" Grid.Column="0" Grid.Row="3" FontSize="24"/> <TextBox x:Name="Endtime" Grid.Column="1" Grid.Row="3" Width="200" Height="40" Text="{Binding EndTime}" FontSize="24"/> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="4"> <Button Content="OK" Margin="10,10" Click="Button_Click_1"/> <Button Content="Cancel" Margin="50,10" Click="Button_Click_2"/> </StackPanel> </Grid> </Border> </StackPanel> </Popup>
修改后台代码如下:
public void Show() { EditItemPopup.IsOpen = true; } private void Button_Click_1(object sender, RoutedEventArgs e) { var schedule = this.DataContext as ScheduleItem; schedule.LessonName = Lessonname.Text; schedule.ClassRoom = Classroom.Text; schedule.StartTime = Starttime.Text; schedule.EndTime = Endtime.Text; EditItemPopup.IsOpen = false; } private void Button_Click_2(object sender, RoutedEventArgs e) { EditItemPopup.IsOpen = false; }
这里的前台做了数据的绑定。后台Button1确定数据更新。
另外在这里多说下,我现在这个编译器,每次在这个用户控件这个页面,鼠标在设计器多晃几下,编译器就有种挂了的感觉,经过研究,其实是设计器的预览模块惹的祸。如果感觉如此,就打开任务管理器。
就会看到如下:
这里圈出来的就是设计器部分,占用率很高,直接把圈出来的这个进程这个终结了就好了。不晓得这个是我机子的原因还是编译器的问题,另外,Vs2012的智能提示不太好,在前台设置的Name属性,在后台智能提示不行,还得生成下才行。
下面修改ItemDetail页面,在Listview后面添加这么一些代码:
<local:EditItemFlyout x:Name="EditFlyout" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="300,200,0,0"/>
并且修改ListView的DoubleTap事件:
private async void ScheduleList_DoubleTapped_1(object sender, DoubleTappedRoutedEventArgs e) { if (ScheduleList.SelectedIndex != -1) { var menu = new PopupMenu(); menu.Commands.Add(new UICommand("Edit", (command) => { EditFlyout.DataContext = ((WeekdayItem)this.DataContext).ScheduleList[ScheduleList.SelectedIndex]; EditFlyout.Show(); })); menu.Commands.Add(new UICommand("Delete", (command) => { ((WeekdayItem)this.DataContext).ScheduleList.RemoveAt(ScheduleList.SelectedIndex); })); await menu.ShowAsync(e.GetPosition(null)); } }
上面代码做了就是显示Flyout和数据的绑定,删除的时候就对数据修改删除就好了。现在编译运行,就能看到弹窗,修改或者删除都能实现了。
下面做Weekdaylist的弹出菜单来作为添加删除等。那么也用DoubleTap事件吧。
WeekdayList的doubleTap事件如下:
private async void weekdayList_DoubleTapped_1(object sender, DoubleTappedRoutedEventArgs e) { var menu = new PopupMenu(); menu.Commands.Add(new UICommand("Add Weekday", (command) => { ItemDetailFrame.Navigate(typeof(AddWeekday), viewModel); })); menu.Commands.Add(new UICommand("Add Schedule", (command) => { if (weekdayList.SelectedIndex != -1) { ItemDetailFrame.Navigate(typeof(AddSchedule), viewModel); } })); menu.Commands.Add(new UICommand("Delete this Item", (command) => { if (weekdayList.SelectedIndex != -1) { viewModel.WeekdayList.RemoveAt(weekdayList.SelectedIndex); } })); await menu.ShowAsync(e.GetPosition(null)); }
addWeekday,Addschedule是两个页面,ItemDetail这个Frame导航到这两个页面,并且传入viewModel这个数据。来实现数据的更新。
现在新建两个页面AddSchedule,AddWeekday到Pages文件夹,代码如下:
AddSchedule前台如下:
<Grid Background="{StaticResource AppBackgroundColor}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Text="LessonName:" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Column="0" Grid.Row="0"/> <TextBox x:Name="Lessonname" Width="200" Height="40" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="1" Grid.Row="0"/> <TextBlock Text="ClassRoom:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="24"/> <TextBox x:Name="Classroom" Grid.Column="1" Grid.Row="1" Width="200" Height="40" HorizontalAlignment="Left" VerticalAlignment="Top"/> <TextBlock Text="StartTime:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="24"/> <TextBox x:Name="Starttime" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="40"/> <TextBlock Text="EndTime:" Grid.Column="0" Grid.Row="3" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="24"/> <TextBox x:Name="Endtime" Grid.Column="1" Grid.Row="3" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="40"/> <Button x:Name="Addschedule" Content="Add" Width="150" Height="40" Click="Addschedule_Click_1" Grid.Column="0" Grid.Row="4" VerticalAlignment="Top" HorizontalAlignment="Center"/> <Button x:Name="Cancel" Content="Cancel" Width="150" Height="40" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Cancel_Click_1" Grid.Column="1" Grid.Row="4"/> </Grid>
上面定义了数据的布局。
后台代码:(添加一个声明和在onnavigateto的时候获取数据源,在点击添加和取消的时候并完成页面导航)
private ViewModel viewModel;
protected override void OnNavigatedTo(NavigationEventArgs e) { viewModel = e.Parameter as ViewModel; } private void Addschedule_Click_1(object sender, RoutedEventArgs e) { if (Lessonname.Text.Length <= 0 || Classroom.Text.Length <= 0 || Starttime.Text.Length <= 0 || Endtime.Text.Length <= 0) { return; } WeekdayItem item = viewModel.WeekdayList[viewModel.SelectedItemIndex]; ScheduleItem scheduleItem = new ScheduleItem(); scheduleItem.LessonName = Lessonname.Text; scheduleItem.ClassRoom = Classroom.Text; scheduleItem.StartTime = Starttime.Text; scheduleItem.EndTime = Endtime.Text; item.ScheduleList.Add(scheduleItem); if (viewModel.SelectedItemIndex == -1) { this.Frame.Navigate(typeof(NoItemSelected)); } else this.Frame.Navigate(typeof(ItemDetail), viewModel); } private void Cancel_Click_1(object sender, RoutedEventArgs e) { if (viewModel.SelectedItemIndex == -1) { this.Frame.Navigate(typeof(NoItemSelected)); } else this.Frame.Navigate(typeof(ItemDetail), viewModel); }
上面用了另一个导航方式,调用了页面的Frame属性来完成导航,另一个页面也是一样的方法,在此附上代码,就不多加解释了。
AddWeekday前台:
<Grid Background="{StaticResource AppBackgroundColor}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Text="WeekDayName:" FontSize="24" Grid.Column="0" Grid.Row="0"/> <TextBox x:Name="WeekdayName" Width="200" Height="40" Grid.Column="1" Grid.Row="0" Margin="0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/> <Button x:Name="Addweekday" Content="Add" Grid.Column="0" Grid.Row="1" Click="AddWeekdayClick" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200"/> <Button x:Name="Cancel" Content="Cancel" Grid.Column="1" Grid.Row="1" Click="CancelClick" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200"/> </Grid>
AddWeekday后台:
private ViewModel viewModel;
protected override void OnNavigatedTo(NavigationEventArgs e) { viewModel = e.Parameter as ViewModel; } private void AddWeekdayClick(object sender, RoutedEventArgs e) { if (WeekdayName.Text.Length <= 0) { return; } WeekdayItem item = new WeekdayItem(); item.Weekday = WeekdayName.Text; viewModel.WeekdayList.Add(item); if (viewModel.SelectedItemIndex == -1) { this.Frame.Navigate(typeof(NoItemSelected)); } else this.Frame.Navigate(typeof(ItemDetail), viewModel); } private void CancelClick(object sender, RoutedEventArgs e) { if (viewModel.SelectedItemIndex == -1) { this.Frame.Navigate(typeof(NoItemSelected)); } else this.Frame.Navigate(typeof(ItemDetail), viewModel); }
到这里,编译运行,就能看到,在左边listView双击添加,删除了。
在这里,提醒大家在用模拟器的时候尽量用模拟手势的选项,在右边工具栏可以选择。这样,就能更好模拟手指了。选项如下图红色方框中。
本次工程下载:http://dl.dbank.com/c0jrblh51s
继续学习:<win8>(四)实例讲解win8(XAML+C#)开发--------课程表:Snapped模式和动态磁贴,徽章(badge)
posted on 2012-07-26 11:44 fengyun1989 阅读(3209) 评论(0) 编辑 收藏 举报