【问题标题】:Bind a Button Flyout Command to a ViewModel's Command in DataTemplate在 DataTemplate 中将按钮弹出命令绑定到 ViewModel 的命令
【发布时间】:2020-05-28 23:20:41
【问题描述】:

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

【问题讨论】:

    标签: c# mvvm view uwp uwp-xaml


    【解决方案1】:

    它编译得很好,但是当我点击编辑按钮时没有任何反应。

    问题是您为MenuFlyoutItem 绑定了错误的Path(Path=DataContext.ViewModel.EditCommand),请删除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>
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 所以我确实忘记设置 MainPage 的 DataContext 它现在可以工作了,谢谢
      猜你喜欢
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 2021-10-25
      • 2019-12-27
      • 2016-11-22
      • 2011-09-17
      • 2019-08-08
      • 2018-07-31
      相关资源
      最近更新 更多