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> TaskLists
,TaskList
class如下;
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
、 中所选 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。
顺便说一句,为了 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
上的可行样本
目前,我正在开发一个简单的任务管理器应用程序来锻炼我的 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> TaskLists
,TaskList
class如下;
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
、 中所选 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。
顺便说一句,为了 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
上的可行样本