ICommand 未将更改推送到 Windows UWP 中的 UI

ICommand not pushing changes to the UI in Windows UWP

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

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

我的命令在 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 中的方法,因为我将 DeleteTask() 方法的主体替换为 await new MessageDialog("").ShowAsync();,它起作用了。

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

更新 上面提到的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> TaskListsTaskListclass如下;

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 绑定到任务列表 ObservableCollection 中所选 TaskListItems 属性,它是第二个 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。

顺便说一句,为了 update/raise CanExecuteChanged,我在这个 case

中使用了 Jerry Nixon - MSFT 提供的解决方案
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

上的可行样本