menuflyout 选择的项目传递给命令 mvvm

Posted

技术标签:

【中文标题】menuflyout 选择的项目传递给命令 mvvm【英文标题】:menuflyout choosed item passing to command mvvm 【发布时间】:2016-07-19 15:55:10 【问题描述】:

我正在尝试将列表视图中所选项目的 menuflyoutitem 绑定到删除命令。 Flyoutmenu 会在我将元素放在列表中时显示,因此我无法将其绑定到 viewmodel 中的 SelectedItem 属性。

SelectedItem 属性工作正常,但我必须先点击元素,然后按住项目以显示菜单,然后删除。如何将发件人从控股传递到我在视图模型中的属性?

查看:

<Grid Background="ThemeResource ApplicationPageBackgroundThemeBrush">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Row="0"
               Text="My List App"
               HorizontalAlignment="Center"
               Style="ThemeResource HeaderTextBlockStyle" />
    <ListView x:Name="myListView"
              Grid.Row="1"
              ItemsSource="Binding AllMyLists"
              SelectedItem="Binding SelectedList, Mode=TwoWay">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <i:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Holding">
                            <controls:OpenMenuFlyoutAction />
                        </core:EventTriggerBehavior>
                    </i:Interaction.Behaviors>
                    <FlyoutBase.AttachedFlyout>
                        <MenuFlyout>
                            <MenuFlyoutItem Text="Delete"
                                            Command="Binding ElementName=myListView, Path=DataContext.DeleteEntryListCommand" />
                        </MenuFlyout>
                    </FlyoutBase.AttachedFlyout>
                    <TextBlock Text="Binding Name"
                               Style="ThemeResource ListViewItemTextBlockStyle" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

OpenMenuFlyoutAction 用于显示 flyoutMenu:

public class OpenMenuFlyoutAction : DependencyObject, IAction

    public object Execute(object sender, object parameter)
    
        FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
        return sender;
    

还有我的 ViewModel:

public class AllListsPageViewModel : Microsoft.Practices.Prism.Mvvm.ViewModel, Interfaces.IAllListsPageViewModel

    #region Fields

    private ObservableCollection<EntryList> _allMyLists;
    private EntryList _selectedList;

    private DelegateCommand _addEntryListCommand;
    private DelegateCommand _deleteEntryListCommand;

    private readonly INavigationService _navigationService;
    #endregion //Fields

    #region Construction

    public AllListsPageViewModel(INavigationService navigationService)  ... 
    #endregion //Construction

    #region Properties

    public ObservableCollection<EntryList> AllMyLists
    
        get  return _allMyLists; 
        set  SetProperty(ref _allMyLists, value); 
    

    public EntryList SelectedList
    
        get  return _selectedList; 
        set  SetProperty(ref _selectedList, value); 
    
    #endregion //Properties

    #region Methods

    private void loadData()  

    private bool _canAddEntryList()  return true; 

    private void _addEntryList()  ... 

    private bool _canDeleteEntryList()  ... 

    private void _deleteEntryList()
    
        //How to get sender from holding event here?
        _allMyLists.Remove(_selectedList);
    
    #endregion //Methods

    #region Commands

    public ICommand AddEntryListCommand  ... 

    public ICommand DeleteEntryListCommand
    
        get
        
            if (_deleteEntryListCommand == null)
            
                _deleteEntryListCommand = new DelegateCommand(_deleteEntryList, _canDeleteEntryList);
            
            return _deleteEntryListCommand;
        
    
    #endregion //Commands

提前致谢。

【问题讨论】:

【参考方案1】:

我今天也遇到了同样的问题,解决方法如下:

namespace your.namespace

    using Microsoft.Xaml.Interactivity;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Input;

    public class OpenMenuFlyoutAction : DependencyObject, IAction
    
        private static object holdedObject;

        public object Execute(object sender, object parameter)
        
            FrameworkElement senderElement = sender as FrameworkElement;
            FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(senderElement);
            flyoutBase.ShowAt(senderElement);

            var eventArgs = parameter as HoldingRoutedEventArgs;
            if (eventArgs == null)
            
                return null;
            

            var element = eventArgs.OriginalSource as FrameworkElement;
            if (element != null)
            
                HoldedObject = element.DataContext;
            

            return null;
        

        public static object HoldedObject
        
            get  return holdedObject; 
            set
            
                holdedObject = value;
            
        
    

那么就可以通过如下方式访问该对象:

var foo = OpenMenuFlyoutAction.HoldedObject as Foo;

我认为 HoldedObject 是静态的并不是一个糟糕的解决方案,因为你不能同时持有两个项目。

【讨论】:

以上是关于menuflyout 选择的项目传递给命令 mvvm的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UWP 中结合 Flyout 和 MenuFlyout?

WinRT 开发:在 MVVM 模式中,关于绑定的几处技巧

背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout

如何将范围名称传递给 lerna 命令动态?

UWP:DataGrid、MenuFlyout 右键单击

如何在 windows phone 8.1 应用程序中使用 MenuFlyout 更改动态生成按钮的内容