<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  阅读(3193)  评论(0编辑  收藏  举报