天天看點

第十九章:集合視圖(十四)

上下文菜單

單元格可以定義以特定于平台的方式調用的上下文菜單。 這樣的上下文菜單通常允許使用者對ListView中的特定項執行操作。 例如,當與顯示學生的ListView一起使用時,這樣的上下文菜單允許使用者對特定學生執行動作。

CellContextMenu程式示範了這種技術。 它定義了一個包含四個項的上下文菜單:

  • 重置GPA(将學生的平均成績設定為2.5)
  • 移至頂部(将學生移至清單頂部)
  • 移動到底部(類似地将學生移到底部)
  • 删除(從清單中删除學生)

在iOS上,通過向左滑動項目來調用上下文菜單。 在Android和Windows 10 Mobile上,您将手指按到該項目并按住它直到出現菜單。 這是結果:

第十九章:集合視圖(十四)

iOS螢幕上隻顯示一個菜單項,這是從清單中删除學生的項目。 必須為iOS特别标記從ListView中删除條目的菜單項。 Android螢幕列出了螢幕頂部的前兩個菜單項。 隻有Windows運作時才會列出它們。

要檢視其他菜單項,請點選iOS上的“更多”按鈕和Android上的垂直省略号。 其他項目顯示在iOS螢幕底部的清單中以及Android螢幕右上角的下拉清單中:

第十九章:集合視圖(十四)

點選其中一個菜單項執行該操作。

要為單元格建立上下文菜單,可以将MenuItem類型的對象添加到Cell類定義的ContextActions集合中。 你已經遇到過MenuItem。 它是第13章“位圖”中描述的ToolbarItem類的基類。

MenuItem定義了五個屬性:

  • 字元串類型的文本
  • FileImageSource類型的圖示,用于從平台項目通路位圖
  • IsDestructive類型為bool
  • 類型為ICommand的指令
  • 類型為object的CommandParameter

此外,MenuItem定義了Clicked事件。 您可以在Clicked處理程式中處理菜單操作,或者如果菜單操作是在ViewModel-ICommand對象中實作的話。

以下是在CellContextMenu程式中初始化ContextActions集合的方法:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:school="clr-namespace:SchoolOfFineArt;assembly=SchoolOfFineArt"
             x:Class="CellContextMenu.CellContextMenuPage">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="0, 20, 0, 0" />
    </ContentPage.Padding>
    <ContentPage.BindingContext>
        <school:SchoolViewModel />
    </ContentPage.BindingContext>
    <StackLayout BindingContext="{Binding StudentBody}">
        <Label Text="{Binding School}"
               FontSize="Large"
               FontAttributes="Bold"
               HorizontalTextAlignment="Center" />
        <ListView ItemsSource="{Binding Students}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ImageCell ImageSource="{Binding PhotoFilename}"
                               Text="{Binding FullName}"
                               Detail="{Binding GradePointAverage,
                               StringFormat='G.P.A. = {0:F2}'}">
                        <ImageCell.ContextActions>
                            <MenuItem Text="Reset GPA"
                                      Command="{Binding ResetGpaCommand}" />
 
                            <MenuItem Text="Move to top"
                                      Command="{Binding MoveToTopCommand}" />
                            <MenuItem Text="Move to bottom"
                                      Command="{Binding MoveToBottomCommand}" />
                            <MenuItem Text="Remove"
                                      IsDestructive="True"
                                      Command="{Binding RemoveCommand}" />
                        </ImageCell.ContextActions>
                    </ImageCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>           

請注意,“删除”項的IsDestructive屬性設定為True。 這是導緻項目在iOS螢幕上以紅色顯示的屬性,按照慣例,該屬性會從集合中删除該項目。

MenuItem定義了一個Icon屬性,您可以将其設定為存儲在平台項目中的位圖(非常類似于ToolbarItem使用的圖示),但它僅适用于Android,并且位圖替換了Text描述。

所有四個MenuItem對象的Command屬性都綁定到Student類中的屬性。

Student對象是單元格的綁定上下文,是以它也是這些MenuItem對象的綁定上下文。 以下是在Student中定義和初始化屬性的方法:

public class Student : ViewModelBase
{
    __
    public Student()
    {
        ResetGpaCommand = new Command(() => GradePointAverage = 2.5);
        MoveToTopCommand = new Command(() => StudentBody.MoveStudentToTop(this));
        MoveToBottomCommand = new Command(() => StudentBody.MoveStudentToBottom(this));
        RemoveCommand = new Command(() => StudentBody.RemoveStudent(this));
    }
    __
    // Properties for implementing commands.
    [XmlIgnore]
    public ICommand ResetGpaCommand { private set; get; }
    [XmlIgnore]
    public ICommand MoveToTopCommand { private set; get; }
    [XmlIgnore]
    public ICommand MoveToBottomCommand { private set; get; }
    [XmlIgnore]
    public ICommand RemoveCommand { private set; get; }
    [XmlIgnore]
    public StudentBody StudentBody { set; get; }
}           

隻有ResetGpaCommand可以在Student類中完全處理。 其他三個指令需要通路StudentBody類中的學生集合。 是以,當首次加載資料時,SchoolViewModel将每個Student對象中的StudentBody屬性設定為帶有學生集合的StudentBody對象。 這允許通過調用StudentBody中的以下方法來實作Move和Remove指令:

public class StudentBody : ViewModelBase
{
    __
    public void MoveStudentToTop(Student student)
    {
        Students.Move(Students.IndexOf(student), 0);
    }
    public void MoveStudentToBottom(Student student)
    {
        Students.Move(Students.IndexOf(student), Students.Count - 1);
    }
    public void RemoveStudent(Student student)
    {
        Students.Remove(student);
    }
}           

由于Students集合是ObservableCollection,是以ListView重繪自身以反映學生的新數字或新順序。

繼續閱讀