首页 > 解决方案 > 在 DataTemplate 中将按钮弹出命令绑定到 ViewModel 的命令

问题描述

我是 UWP 的新手,我正在尝试从每个项目上显示的列表视图中的按钮弹出窗口绑定到我的 ViewModel 中的事件。我在网上查看了许多解决方案并提出了以下代码,它编译得很好,但是当我单击所述编辑按钮时没有任何反应。

我的 ViewModel 可从 Page 的上下文而不是 Item 的上下文中获得

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);
        }
    }
}

标签: c#mvvmviewuwpuwp-xaml

解决方案


它编译得很好,但是当我单击所述编辑按钮时,什么也没有发生。

问题是您为 绑定错误Path(Path=DataContext.ViewModel.EditCommand) MenuFlyoutItem,请删除ViewModel字段。我已经编辑了您的代码,请参考以下内容。

<Page.DataContext>
    <local:MainPageViewModel x:Name="ViewModel"/>
</Page.DataContext>
 ......
<Button
    Grid.Column="1"
    Width="30"
    Height="30"
    >
    <Button.Flyout>
        <MenuFlyout>
            <MenuFlyoutItem
                Command="{Binding ElementName=MainListView, Path=DataContext.EditCommand}"
                CommandParameter="{Binding}"
                Icon="Edit"
                Text="Edit"
                />
        </MenuFlyout>
    </Button.Flyout>
</Button>

推荐阅读