c# – 自定义视图中的BindableProperty不会取消订阅PropertyChanged
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 自定义视图中的BindableProperty不会取消订阅PropertyChanged,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4809字,纯文字阅读大概需要7分钟。
内容图文
![c# – 自定义视图中的BindableProperty不会取消订阅PropertyChanged](/upload/InfoBanner/zyjiaocheng/788/f0033cef34894ba3b7ac093843bfcecb.jpg)
背景信息
我正在使用MVVM和View第一种方法在XAML中开发Xamarin Forms(v4.1.1.3,在iOS上测试)应用程序;我正在使用MVVMLight的ViewModelLocator服务将单实例ViewModel分配给Views:
BindingContext="{Binding [SearchViewModel], Source={StaticResource ViewModelLocator}}"
导航到另一个页面时,我正在构建一个新的页面实例,每次都会收到相同的ViewModel实例.
var page = new SearchView();
var tabbedPage = Application.Current.MainPage as TabbedPage;
if (tabbedPage != null)
await tabbedPage.CurrentPage.Navigation.PushAsync(page);
问题
我已经实现了一个自定义控件(视图?),它应该以类似于tile的布局显示搜索结果.在从搜索NavigationPage导航到搜索结果ContentPage时创建此控件.
每次我返回搜索页面并导航回搜索结果时,都会重建视图并订阅BindableProperties的PropertyChanged.这些PropertyChanged事件永远不会取消订阅,因此每次我导航到搜索结果视图并更改绑定的ViewModel属性时,事件会多次触发.
在以下代码中,根据我从搜索视图导航到搜索结果视图的次数,多次触发OnItemsPropertyChanged:
public class WrapLayout : Grid
{
public static readonly BindableProperty ItemsProperty =
BindableProperty.Create("Items", typeof(IEnumerable), typeof(WrapLayout), null, propertyChanged: OnItemsPropertyChanged);
public IEnumerable Items
{
get { return (IEnumerable)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public WrapLayout()
{
...
}
private static void OnItemsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
...
}
}
我的问题:
> BindableProperty不应该取消订阅PropertyChanged并自行更改吗?
>这是因为我将View与ViewModel关联和/或浏览页面的方式吗?
>我应该自己处理取消订阅这些事件,以及如何处理?
编辑;其他导航信息
我有一个MainView TabbedPage,它将SearchView创建为NavigationPage:
public MainView()
{
InitializeComponent();
Children.Add(new NavigationPage(new SearchView())
{
Title = AppResources.Tab_Search,
Icon = "tab_search"
});
}
SearchView在创建时,使用MVVMLight的SimpleIoc容器,在本主题开头提到的ViewModelLocator分配的单实例ViewModel.
当触发SearchView中的搜索命令时,我向API返回搜索结果的请求.这些结果显示在另一个页面上,我从SearchView的ViewModel导航到该页面:
await _navigationService.NavigateTo(ViewModelLocator.PageKeyFileResults, searchResult);
哪个功能看起来像这样:
public async Task NavigateTo(string pagekey, object viewModelParameter)
{
var constructor = _pagesByKey[pagekey].Constructor; //Gets the Func<Page> that simple creates the requested page, without using reflection.
var page = constructor() as Page;
var viewModel = page.BindingContext as BaseViewModel;
if (viewModel != null)
viewModel.Initialize(viewModelParameter);
var tabbedPage = Application.Current.MainPage as TabbedPage;
if (tabbedPage != null)
await tabbedPage.CurrentPage.Navigation.PushAsync(page);
else
await Application.Current.MainPage.Navigation.PushAsync(page);
}
构造的页面看起来有点像:
<pages:BaseContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Views.FileResultsView"
xmlns:pages="clr-namespace:Views.Pages;assembly=Views"
xmlns:controls="clr-namespace:Views.Controls;assembly=Views"
BindingContext="{Binding [FileResultsViewModel], Source={StaticResource ViewModelLocator}}">
<ScrollView>
<controls:WrapLayout
Items="{Binding SearchResults}" />
</ScrollView>
</pages:BaseContentPage>
BaseContentPage的位置是:
public class BaseContentPage : ContentPage
{
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Subscribe<DialogMessage>(this, "ShowDialog", (dialogMessage) =>
{
if (string.IsNullOrWhiteSpace(dialogMessage.AcceptButton))
DisplayAlert(dialogMessage.Title, dialogMessage.Content, dialogMessage.CancelButton);
else
DisplayAlert(dialogMessage.Title, dialogMessage.Content, dialogMessage.AcceptButton, dialogMessage.CancelButton);
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<DialogMessage>(this, "ShowDialog");
}
}
ViewModel基本上是这样的:
public class FileResultsViewModel : BaseViewModel
{
private IEnumerable<ASRow> _searchResults;
public IEnumerable<ASRow> SearchResults
{
get { return _searchResults; }
set { Set(ref _searchResults, value); }
}
internal override void Initialize(object parameter)
{
base.Initialize(parameter);
if (parameter is AdvancedSearchResponse)
{
var searchResults = parameter as AdvancedSearchResponse;
SearchResults = new List<ASRow>(searchResults.Rows);
}
}
}
解决方法:
> BindableProperty不应该取消订阅PropertyChanged并自行更改吗?
不.Binding类负责这一点.不是BindableProperty.
>这是因为我将View与ViewModel关联和/或浏览页面的方式吗?
您正在看到这一点,因为您忘记了导航堆栈在内存中保留了一个页面列表.由于多个页面指向相同的BindingContext,因此有多个观察者可以进行更改.如果您不重复使用View Models,则不会遇到此特定问题.
>我应该自己处理取消订阅这些事件,以及如何处理?
不.如果真的是一个问题,那么当页面消失时将BindingContext设置为null,然后在重新出现时将其恢复.请记住,虽然这仍然有成本,特别是如果您的UI非常繁忙并且有大量由数据绑定控制的动态内容.
内容总结
以上是互联网集市为您收集整理的c# – 自定义视图中的BindableProperty不会取消订阅PropertyChanged全部内容,希望文章能够帮你解决c# – 自定义视图中的BindableProperty不会取消订阅PropertyChanged所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。