c# – ICommand没有将更改推送到Windows UWP中的UI

目前,我正在开发一个简单的任务管理器应用程序,以使用通用
Windows应用程序(UWP)模板和MVVM设计模式来运用我的Windows 10开发技能.

在我的ViewModel(实现INotifyPropertyChanged)中,我有一个ObservableCollection< BasicTask>它是数据绑定到XAML中的ListView,其中BasicTask是我开发的一个简单类.

我的命令在ViewModel中作为属性进行实例化,并且数据绑定到(在这种情况下)AppBarButton UI元素的“Command”属性.该命令的功能是调用ViewModel中的一个方法,该方法在命令的构造函数中定义,如此;

class DeleteTaskCommand : ICommand
{
    public DeleteTaskCommand(MainViewModel viewModel)
    {
        ViewModel = viewModel;
    }

    public MainViewModel ViewModel { get; private set; }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter) => (ViewModel.SelectedTask != BasicTask.Default) ? true : false;

    public void Execute(object parameter) => ViewModel.DeleteTask();
}

ViewModel中的DeleteTask()方法会影响ObservableCollection< BasicTask>,正如我之前所说,它是数据绑定到ListView,因此(据我所知)应该立即将更改推送到ListView.而这正是不做的事:(

我可以确认该命令正确地调用了ViewModel中的方法,因为我用等待新的MessageDialog(“”)替换了DeleteTask()方法的主体.显示了ShowAsync();.

到目前为止,我已经尝试过许多项目并没有成功.一个明显的解决方案是here,但Visual Studio通知CommandManager类不存在:/

《c# – ICommand没有将更改推送到Windows UWP中的UI》

UPDATE
上面提到的ListView的XAML如下:

<ListView ItemsSource="{Binding TaskLists}"
SelectedIndex="{Binding SelectedTaskListIndex, Mode=TwoWay}"
SelectionMode="Single">
<ListView.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <Grid>[...]</Grid>
            <TextBlock Text="{Binding Title}"/>
        </StackPanel>
    </DataTemplate>
</ListView.ItemTemplate>

TaskLists是一个ObservableCollection< TaskList> TaskLists和TaskList类如下;

class TaskList
{
    public string Title { get; set; }
    public string Description { get; set; }
    public List<BasicTask> Items { get; set; }

    public static TaskList Generate(string title, string description, List<BasicTask> items) 
        => new TaskList() { Title = title, Description = description, Items = items };
}

第二个ListView绑定到TaskLists ObservableCollection中所选TaskList的Items属性,它是第二个未更新的ListView.

public int SelectedTaskListIndex
    {
        get { return selectedTaskListIndex; }
        set
        {
            selectedTaskListIndex = value;
            SelectedTaskList = (value != -1) ? TaskLists[value] : TaskList.Default;
            RaisePropertyChanged(nameof(SelectedTaskListIndex));
        }
    }

    public TaskList SelectedTaskList
    {
        get { return selectedTaskList; }
        set
        {
            selectedTaskList = value;
            RaisePropertyChanged(nameof(SelectedTaskList));
        }
    }
<ListView ItemsSource="{Binding SelectedTaskList.Items}"

任何和所有这个问题的帮助将不胜感激:)

最佳答案

In my ViewModel (which implements INotifyPropertyChanged), I’ve got an
ObservableCollection which is databound to a ListView in
XAML

class TaskList {
public string Title { get; set; }
public string Description { get; set; }
public List Items { get; set; } … }

实际上,我注意到你在TaskList中创建了一个List属性,如果用ObservableCollection替换它并以正确的方式通知UI,UI更新应该有效,这是我的DeleteTask()方法:

private void DeleteTask()
{
            SelectedTaskList.Items.Remove(SelectedTask);
}

SelectedTaskList和SelectedTask都已及时通知UI.

顺便说一下,为了更新/提升CanExecuteChanged,我使用了Jerry Nixon提供的这个解决方案 – MSFT在这个case

public TaskList SelectedTaskList
{
            get { return selectedTaskList; }
            set
            {
                selectedTaskList = value;
                RaisePropertyChanged(nameof(SelectedTaskList));
                DeleteTaskCommand.RaiseCanExecuteChanged();
            }
}

public BasicTask SelectedTask
{
            get { return selectedTask; }
            set
            {
                selectedTask = value;
                RaisePropertyChanged(nameof(SelectedTask));
                DeleteTaskCommand.RaiseCanExecuteChanged();
            }
}

请在Github检查我的可行样本

点赞