x:将ViewModel方法绑定到DataTemplate中的Event

我基本上问的是和这个人一样的问题,但是在新的x:Bind的背景下。

ViewModels的DataContext定义如下

    

因此,每当我需要绑定某些东西时,我就会明确地对ViewModel这样做

 ItemsSource="{x:Bind ViewModel.pageList, Mode=OneWay}" 

但是,这在模板中不起作用

     <-- this here is the culprit      

阅读文档,我发现使用Path应该基本上将上下文重置为页面,但是这个( x:Bind Path=ViewModel.PageResizeEvent也不起作用。我仍然Object reference not set to an instance of an object ,这应该意味着它没有看到方法(但是null)。

图像类:

 public class Image { public int page { get; set; } public string url { get; set; } public int width { get; set; } public int heigth { get; set; } } 

并在ChapterPageViewModel中

 private List _pageList; public List pageList { get { return _pageList; } set { Set(ref _pageList, value); } } public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary suspensionState) { Initialize(); await Task.CompletedTask; } private async void Initialize() { pageList = await ComicChapterGet.GetAsync(_chapterId); } public void PageResized(object sender, SizeChangedEventArgs e) { //resizing logic happens here } 

我们这里有两个问题:

首先, 尝试将事件直接绑定到事件处理程序委托

简单地说,这将永远不会奏效。
处理MVVM模式事件的一种方法是使用EventTrigger和ICommand。
它需要一个实现ICommand的类。 如果不知道如何操作, 这篇文章将对你有所帮助。 我会打电话给我的DelegateCommand

以下是我将通过两个步骤重构它的方法:

1)向VM添加命令:

 public class ChapterPageViewModel { public ChapterPageViewModel() { this.PageResizedCommand = new DelegateCommand(OnPageResized); } public DelegateCommand PageResizedCommand { get; } private void OnPageResized() { } } 

2)使用EventTrigger和InvokeCommandAction将该命令绑定到SizeChanged事件。

  (...)                

“但加布里埃尔” ,你说, “那不起作用!”

我知道! 这是因为第二个问题,即试图x:绑定一个不属于DataTemplate类的属性

这个与这个问题密切相关,所以我会从那里借一些信息。

从MSDN,关于DataTemplate和x:Bind

在DataTemplate内部(无论是用作项目模板,内容模板还是标题模板),Path的值不会在页面的上下文中解释,而是在被模板化的数据对象的上下文中解释。 因此,在编译时可以validation其绑定(以及为它们生成有效的代码),DataTemplate需要使用x:DataType声明其数据对象的类型。

因此,当您执行 ,您实际上是在该models:Image上搜索名为ViewModel的属性models:Image类,它是DataTemplate的x:DataType 。 并且该类不存在这样的属性。

在这里,我可以看到两个选项。 选择其中一个

将ViewModel添加为Image类的属性,并将其填充到VM上。

 public class Image { (...) public ChapterPageViewModel ViewModel { get; set; } } public class ChapterPageViewModel { (...) private async void Initialize() { pageList = await ComicChapterGet.GetAsync(_chapterId); foreach(Image img in pageList) img.ViewModel = this; } } 

只有这一点,以前的代码应该工作,不需要改变任何其他东西。

删除x:绑定并使用ElementName返回到良好的ol’Binding。

               

这种方式会破坏你的问题的目的,但它确实有效,而且比以前更容易。