WPF CommandParameter值在执行时更改为null

我正在学习C#WPF,此刻我面临一个问题。


应用程序:

我正在玩MVVM模式。
我建立了一个简单的应用程序,其中仅包含
-一个ListView,显示UserControl的简单集合,
-一个将新项目添加到ListView和
的按钮 -a ContextMenu,该菜单应允许用户编辑SelectedItem。


问题:

我的ViewModel中有一个SelectedItem属性,它作为commandparameter传递给我的一个Commands。更具体地说,应该允许用户在ListView.SelectedItem UserControl中编辑文本的CmdItemBeginEdit。
我已经在TwoWay模式下将属性绑定到ListView.SelectedItem,并且还在相应控件中将属性绑定为commandparameter
事实是,虽然在选择ListView项时正确设置了SelectedItem,但要执行Command的时间到了,它变为null。
为什么会这样呢?


更新#1

我找到了一些与我的问题有关的信息。它与Command或类似命令的执行顺序有关,似乎是.NET Framework错误(该死的microsoft)。
其他成员建议在XAML中在Command之前定义commandparameter,并首先将Command的IsAsync属性启用为true。我都尝试过,但都没用。
你听到过类似的话吗?


代码:

请注意,已经实现了许多技术和先决条件,例如ICommand(命令和commandparameter),模型和ViewModel上的INotifyPropertyChanged,ObservableCollection,Binding等。

我的项目包括:
- MainWindow.xaml (查看)

<Window x:Class="Demo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Demo"
    xmlns:uc="clr-namespace:Demo.Views.UserControls"
    xmlns:vm="clr-namespace:Demo.ViewModels"
    mc:Ignorable="d"
    Title="Demo"
    Height="300"
    Width="300"
    WindowStartupLocation="CenterScreen">

<!--To apply to Window level-->
<Window.DataContext>
    <vm:MainVM />
</Window.DataContext>

<Window.Resources>
    <!--For referencing-->
    <vm:MainVM x:Key="VM" />
</Window.Resources>

<StackPanel>
    <Button x:Name="btnAddItem"
            Content="Add"
            Width="150"
            Command="{Binding ItemNew}" />
    <ListView x:Name="lviewColelction"
              Width="150"
              MinHeight="100"
              HorizontalContentAlignment="Stretch"
              ItemsSource="{Binding Items}"
              SelectedItem="{Binding SelectedItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <uc:Item DataSource="{Binding}" />

                    <StackPanel.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Rename"
                                      Command="{Binding Source={StaticResource VM},Path=ItemBeginEdit}"
                                      commandparameter="{Binding Source={StaticResource VM},Path=SelectedItem}" />
                        </ContextMenu>
                    </StackPanel.ContextMenu>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackPanel>

- MainVM.cs (ViewModel)

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Demo.ViewModels
{
    public class MainVM : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged implementation
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string PropertyName = "")
        {
            var args = new PropertyChangedEventArgs(PropertyName);
            PropertyChanged?.Invoke(this,args);
        }
        #endregion

        //Properties 
        public ObservableCollection<Models.CustomItem> Items { get; set; }

        private Models.CustomItem selectedItem;
        public Models.CustomItem SelectedItem
        {
            get { return selectedItem; }
            set
            {
                if (value == null)
                    return;
                if (value == selectedItem)
                    return;

                selectedItem = value;
                OnPropertyChanged();
            }
        }

        public Commands.CmdItemNew ItemNew { get; set; }
        public Commands.CmdItemBeginEdit ItemBeginEdit { get; set; }
        public Commands.CmdItemEndEdit ItemEndEdit { get; set; }

        //Constructors 
        public MainVM()
        {
            Items = new ObservableCollection<Models.CustomItem>();
            SelectedItem = null;
            ItemNew = new Commands.CmdItemNew(this);
            ItemBeginEdit = new Commands.CmdItemBeginEdit(this);
            ItemEndEdit = new Commands.CmdItemEndEdit(this);

            ReadItems();
        }

        //Methods
        public void SetupItems()
        {
            //Just create demo items. Not used. 
            var items = DatabaseHelper.ReadItems();
            int itemsToCreate = 3 - items.Length;
            while (itemsToCreate > 0)
            {
                CreateItem();
                itemsToCreate--;
            }
        }

        public void CreateItem()
        {
            var item = new Models.CustomItem()
            {
                Name = "New Item"
            };
            DatabaseHelper.Insert(item);
        }

        public void ReadItems()
        {
            var items = DatabaseHelper.ReadItems();
            Items.Clear();
            foreach (var item in items)
                Items.Add(item);
        }
    }
}

- CustomItem.cs (模型)

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using SQLite;

namespace Demo.Models
{
    public class CustomItem
    {
        #region INotifyPropertyChanged implementation
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string PropertyName = "")
        {
            if (PropertyChanged != null)
            {
                var args = new PropertyChangedEventArgs(PropertyName);
                PropertyChanged.Invoke(this,args);
            }
        }
        #endregion

        //Properties 
        private int id;
        [PrimaryKey,AutoIncrement]
        public int Id
        {
            get { return id; }
            set
            {
                if (value != id)
                {
                    id = value;
                    OnPropertyChanged();
                }
            }
        }

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                if (value != name)
                {
                    name = value;
                    OnPropertyChanged();
                }
            }
        }

        private bool isEditing;
        [Ignore]
        public bool IsEditing
        {
            get
            {
                return isEditing;
            }
            set
            {
                if (value != isEditing)
                {
                    isEditing = value;
                    OnPropertyChanged();
                }
            }
        }
    }
}

- CmdItemBeginEdit.cs (ICommand)

using System;
using System.Windows.Input;

namespace Demo.ViewModels.Commands
{
    public class CmdItemBeginEdit : ICommand
    {
        #region ICommand implementation 
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public void Execute(object parameter)
        {
            var item = parameter as Models.CustomItem;
            if (item == null)
                return;

            item.IsEditing = true;
        }
        #endregion

        //Properties
        public MainVM VM { get; set; }

        //Constructors 
        public CmdItemBeginEdit(MainVM VM)
        {
            this.VM = VM;
        }
    }
}

- CmdItemNew.cs (ICommand)

using System;
using System.Windows.Input;

namespace Demo.ViewModels.Commands
{
    /// <summary>
    /// We are going to assign a Command for each Button. 
    /// </summary>
    public class CmdItemNew : ICommand
    {
        #region ICommand implementation 
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public void Execute(object parameter)
        {
            VM.CreateItem();
            VM.ReadItems();
        }
        #endregion

        //Properties 
        public MainVM VM { get; set; }

        //Constructor 
        public CmdItemNew(MainVM VM)
        {
            this.VM = VM;
        }
    }
}
iCMS 回答:WPF CommandParameter值在执行时更改为null

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/2226397.html

大家都在问