2016-04-20 30 views
6

Sto cercando in internet come aggiungere il menu di scelta rapida per ListView. Finora ho trovato uno che in realtà mostra contestoMenu di scelta rapida ListWall UWP

<ListView> 
    ... 
    RightTapped="ContactsListView_RightTapped" > 
    ... 
    <ListView.Resources> 
     <MenuFlyout x:Name="allContactsMenuFlyout"> 
      <MenuFlyout.Items> 
       <MenuFlyoutItem x:Name="Edit" Text="Edit"/> 
       <MenuFlyoutItem x:Name="Remove" Text="Remove" Click="Remove_Click"/> 
      </MenuFlyout.Items> 
     </MenuFlyout> 
    </ListView.Resources> 
    ... 
</ListView> 

private void ContactsListView_RightTapped(object sender, RightTappedRoutedEventArgs e) { 
    ListView listView = (ListView)sender; 
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView)); 
} 

private void Remove_Click(object sender, RoutedEventArgs e) { 

} 

Il problema è che non sono in grado di ottenere punto in cui è stato visualizzato il menu di scelta rapida. Un altro problema è che il menu di scelta rapida viene visualizzato anche al di fuori dell'elemento della vista elenco (ad es. Sui bordi). E poiché l'evento che viene attivato è RightTapped, non sono sicuro che il menu di scelta rapida verrà visualizzato in un clic lungo sui dispositivi mobili. Non riesco a testarlo perché i miei emulatori non funzionano al momento. Dato che dovrebbe essere l'app universale per Windows, mi aspettavo un modo davvero semplice ed efficace per creare menu contestuali per gli oggetti di ListView.

risposta

9

Il problema è che non sono in grado di ottenere punto in cui è stato visualizzato il menu di scelta rapida.

Per questo problema, se si aggiungono i dati al ListView in questo modo:

È possibile ottenere il contesto del prodotto in caso RightTapped in questo modo:

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e) 
{ 
    ListView listView = (ListView)sender; 
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView)); 
    var a = ((FrameworkElement)e.OriginalSource).DataContext; 
} 

In questo scenario , "a" otterrà direttamente il contenuto in formato stringa dell'elemento selezionato.

se si aggiungono i dati di ListView utilizzando DataTemplate come questo:

<ListView RightTapped="ListView_RightTapped" ItemsSource="{x:Bind list}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding text}" /> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
    <ListView.Resources> 
     <MenuFlyout x:Name="allContactsMenuFlyout"> 
      <MenuFlyout.Items> 
       <MenuFlyoutItem x:Name="Edit" Text="Edit" /> 
       <MenuFlyoutItem x:Name="Remove" Text="Remove" Click="Remove_Click" /> 
      </MenuFlyout.Items> 
     </MenuFlyout> 
    </ListView.Resources> 
</ListView> 

e di solito quando si utilizza DataTemplate, aggiungiamo i dati da ObservableCollection come questo:

private ObservableCollection<List> list = new ObservableCollection<List>(); 

public MainPage() 
{ 
    this.InitializeComponent(); 
    list.Clear(); 
    list.Add(new List { text = "Item 1" }); 
    list.Add(new List { text = "Item 2" }); 
    list.Add(new List { text = "Item 3" }); 
    list.Add(new List { text = "Item 4" }); 
    list.Add(new List { text = "Item 5" }); 
} 

"Lista" di classe è abbastanza semplice qui per la prova:

public class List 
{ 
    public string text { get; set; } 
} 

Poi anche possiamo ottenere il DataContext in RightTapped evento:

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e) 
{ 
    ListView listView = (ListView)sender; 
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView)); 
    var a = ((FrameworkElement)e.OriginalSource).DataContext; 
} 

Ma questa volta, "a" è in realtà la 'Lista' oggetto (si prega di fare riferimento alla classe "List") all'interno della voce, perché la il contenuto dell'elemento ora è un oggetto 'Elenco', non più una stringa. Così possiamo ottenere la proprietà testo di questo oggetto come questo:

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e) 
{ 
    ListView listView = (ListView)sender; 
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView)); 
    var a = ((FrameworkElement)e.OriginalSource).DataContext as List; 
    var content = a.text; 
} 

Penso che alla fine si desidera modificare il contenuto in caso Button click del Flyout, si può fare per esempio come questo:

private string content; 

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e) 
{ 
    ListView listView = (ListView)sender; 
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView)); 
    var a = ((FrameworkElement)e.OriginalSource).DataContext as List; 
    content = a.text; 
} 

private void Remove_Click(object sender, RoutedEventArgs e) 
{ 
    foreach (var item in list.ToList()) 
    { 
     if (item.text == content) 
     { 
      list.Remove(item); 
     } 
    } 
    content = ""; 
} 

Un altro problema è che il menu di scelta rapida viene visualizzato anche al di fuori dell'elemento di visualizzazione elenco (ad esempio sui bordi).

Puoi spiegare questo? Non riesco a capirlo.Intendi la visualizzazione del contenuto, ad esempio nello Flyout? Se è così, penso che il metodo sopra possa risolvere questo problema. In caso contrario, puoi lasciare un commento e vedrò se questo problema può essere risolto.

E poiché l'evento che viene attivato è RightTapped, non sono sicuro se il menu di scelta rapida verrà visualizzato sul clic lungo sui dispositivi mobili.

Penso che l'evento "clic lungo" qui indichi l'evento Holding come questo?

private void ListView_Holding(object sender, HoldingRoutedEventArgs e) 
{ 
    ListView listView = (ListView)sender; 
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView)); 
    var a = ((FrameworkElement)e.OriginalSource).DataContext as List; 
    content = a.text; 
} 

Ho appena testato su Mobile Emulator, funziona bene. Anche se ho scritto una risposta piuttosto lunga qui, ma il punto chiave è abbastanza semplice, puoi semplicemente usare ((FrameworkElement)e.OriginalSource).DataContext per ottenere il Contesto dell'oggetto.

3

Utilizzare il comando anziché l'evento Click. È possibile passare l'oggetto cliccato in CommandParameter

<MenuFlyout x:Name="allContactsMenuFlyout"> 
       <MenuFlyout.Items> 
        <MenuFlyoutItem x:Name="Edit" Text="Edit"/> 
        <MenuFlyoutItem x:Name="Remove" Text="Remove" Command="{Binding Path=DataContext.DeleteItemTappedCommand , ElementName=ListViewName}" CommandParameter="{Binding }"/> 
       </MenuFlyout.Items> 
      </MenuFlyout> 

In viewModel.cs 
    public DelegateCommand<object> DeleteItemTappedCommand { get; set; } 

public viewModel() 
{ 
DeleteItemTappedCommand = new DelegateCommand<object>(DeleteItemClicked); 
} 
private void DeleteItemClicked(object obj) 
{ 
//Your code. Here obj is clicked item 
} 
+0

THX per la risposta. Ci proverò. Ma l'evento che fa scattare questo è ancora fare clic destro sulla visualizzazione elenco. Quindi verrà attivato e. g. quando faccio clic con il pulsante destro del mouse sull'intestazione di un gruppo nella visualizzazione elenco o su un bordo. Mi aspettavo qualcosa di veramente facile da implementare, poiché questa è una funzionalità comune. – miskohut

+0

Il binding ha senso ma è sempre 'null'. Non ho avuto successo a ottenere la proprietà 'Command' da allegare a qualsiasi cosa. –

+0

Provare a utilizzare 'Behaviors' e' InvokeCommandAction' dal framework prisma – Archana

0

Aggiungi flyout nel datatemplate. Usa il comando per gestire gli eventi. See codice di esempio qui:

<DataTemplate x:Name="ListItemTemplate" > 
    <Grid x:Name="gridItem" RightTapped="gridItem_RightTapped"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="auto"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <Image Name="imgProduct" Width="50" Height="50" Grid.Column="0" Source="{Binding ProductUrl}" Margin="0,5,10,5" VerticalAlignment="Center" ></Image> 
     <TextBlock Name="tbName" Text="{Binding Name}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Stretch" ></TextBlock> 
     <FlyoutBase.AttachedFlyout> 
      <MenuFlyout> 
       <MenuFlyoutItem Text="Delete" Command="{Binding DataContext.DeleteCommand, ElementName=contentGrid}" CommandParameter="{Binding}" /> 
      </MenuFlyout> 
     </FlyoutBase.AttachedFlyout> 
    </Grid> 
</DataTemplate> 

codice dietro:

private void gridItem_RightTapped(object sender, RightTappedRoutedEventArgs e) 
{ 
    FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement); 
} 

è possibile ottenere la soluzione completa: https://code.msdn.microsoft.com/How-to-implement-flyout-ef52517f

Problemi correlati