温馨提示:本文翻译自stackoverflow.com,查看原文请点击:c# - Bind a Button Flyout Command to a ViewModel's Command in DataTemplate
c# mvvm uwp uwp-xaml view

c# - 将按钮弹出按钮绑定到DataTemplate中的ViewModel命令

发布于 2020-05-03 00:13:00

我是UWP的新手,我想通过每个项目上显示的列表视图中的按钮弹出按钮绑定到ViewModel中的事件。我在网上查看了许多解决方案,并想到了以下代码,它可以很好地编译,但是当我单击所说的“编辑”按钮时,什么都没有发生。

我的ViewModel在页面的上下文中可用,而不在项目的上下文中可用

XAML

<ListView x:Name="MainListView"
                  ItemsSource="{x:Bind ViewModel.Devices, Mode=OneWay}"
                  SelectionMode="Multiple" 
                  SelectionChanged="MainListView_SelectionChanged">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid Width="Auto">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="0*"></ColumnDefinition>
                            <ColumnDefinition Width=".4*"></ColumnDefinition>
                            <ColumnDefinition Width="3*"></ColumnDefinition>
                            <ColumnDefinition Width="3*"></ColumnDefinition>
                            <ColumnDefinition Width="3*"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Column="2" Text="{Binding AssetNumber}"/>
                        <TextBlock Grid.Column="3" Text="{Binding SerialNumber}"/>
                        <TextBlock Grid.Column="4" Text="{Binding Model}"/>
                        <Button Grid.Column="1" Height="30" Width="30">
                            <Button.Flyout>
                                <MenuFlyout>
                                    <MenuFlyoutItem Text="Edit" Icon="Edit"
                                                    Command="{Binding ElementName=MainListView,Path=DataContext.ViewModel.EditCommand}"
                                                    CommandParameter="{Binding}"/>
                                </MenuFlyout>
                            </Button.Flyout>
                        </Button>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

查看模型类别

public class MainPageViewModel
{
    // Elements contained in the main listview 
    public ObservableCollection<Device> Devices = new ObservableCollection<Device>();

    public MainPageViewModel()
    {
        DeviceProvider.Fill(ref Devices, 100);
        EditCommand = new RelayCommand<Device>(EditDevice);
    }

    public RelayCommand<Device> EditCommand { get; set; }
    private async void EditDevice(Device device)
    {
        // Code here that creates a dialog
    }
}

设备类

public class Device : INotifyPropertyChanged
{
    private string assetNumber;
    private string serialNumber;
    private string model;
    public string AssetNumber
    {
        get
        {
            return assetNumber;
        }
        set
        {
            assetNumber = value;
            OnPropertyChanged();
        }
    }
    public string SerialNumber
    {
        get
        {
            return serialNumber;
        }
        set
        {
            serialNumber = value;
            OnPropertyChanged();
        }
    }
    public string Model
    {
        get
        {
            return model;
        }

        set
        {
            model = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

RelayCommand类

public class RelayCommand<T> : ICommand
{
    private readonly Action<T> _execute;
    private readonly Func<bool> _canExecute;

    public event EventHandler CanExecuteChanged;

    public RelayCommand(Action<T> execute) : this(execute, null)
    {
    }

    public RelayCommand(Action<T> execute, Func<bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        var handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

查看更多

提问者
Matt
被浏览
22
ardget 2020-02-14 15:01

您的代码似乎没有任何问题。因此,它应该工作完美。但是,如果没有,我怀疑MainPage.ViewModel成员可能未正确定义。{Binding}中使用的属性必须是“ public”,并且必须具有“ get”访问器。

public sealed partial class MainPage : Page
{
    public MainPageViewModel ViewModel { get; set; } = new MainPageViewModel();

    public MainPage()
    {
        this.InitializeComponent();
        DataContext = this;
    }
}