如何在父标签页 xamarin 表单中更新徽章计数器
How to update badge counter in Parent tab page xamarin forms
我有一个使用标签页的应用程序,在父标签页的 xaml
我填充了所有其他标签页,我有一个视图模型绑定到每个其他标签页的父标签页和视图模型。我在其中一个选项卡上有一个徽章,上面有一个计数器,显示有多少条消息。
我在更新计数器时遇到问题。
所以我有一个调用来从数据库中检索未读消息的数量,这些消息在应用程序加载时填充到计数器中。当我导航查看消息时,它会更新消息已被读取的数据库,然后我使用 popasync 导航回到选项卡式页面,然后我拉动以刷新执行调用以获取已读取消息的数量但它不会更新计数器,如果我在 GetCounter 方法上放置一个断点,我会看到它正在用正确的数量更新计数器,但没有改变徽章。
希望这是有道理的。
如果有人能提供帮助,我将不胜感激。
主标签页:
<NavigationPage Title="Message" Icon="email.png" plugin:TabBadge.BadgeText="{Binding counter}"
plugin:TabBadge.BadgeColor="Red"
plugin:TabBadge.BadgePosition="PositionTopRight"
plugin:TabBadge.BadgeTextColor="Green">
<x:Arguments>
<local:MessagePage BindingContext="{Binding messages}" />
</x:Arguments>
</NavigationPage>
public partial class MasterTabPage : TabbedPage
{
Master_PageViewModel vm;
public MasterTabPage ()
{
InitializeComponent ();
this.BindingContext = vm = new Master_PageViewModel(Navigation);
}
}
主标签页 ViewModel:
public class Master_PageViewModel : INotifyPropertyChanged
{
INavigation Navigation;
private int _counter;
public int counter
{
get => _counter;
set
{
_counter = value;
OnPropertyChanged(nameof(counter));
}
}
public MessagePageViewModel messages { get; set; }
public Master_PageViewModel(INavigation navigation)
{
Navigation = navigation;
messages = new MessagePageViewModel(Navigation);
Init();
counter = 0;
}
public async void Init()
{
await GetCounter();
}
public async Task GetCounter()
{
try
{
using (HttpClient client = new HttpClient())
{
List<MessageModel> msg = new List<MessageModel>();
using (HttpResponseMessage response = await client.GetAsync("http://localhost:53665/api/GetMessagesCount/Id=" + 2 + "/" ))
{
if (response.IsSuccessStatusCode)
{
using (HttpContent content = response.Content)
{
var textresponse = await content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<List<MessageModel>>(textresponse);
foreach (var i in json)
{
msg.Add(new MessageModel
{
msgCounter = i.msgCounter,
});
}
counter = msg[0].msgCounter;
}
}
else
{
}
}
}
}
catch (Exception)
{
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
消息选项卡视图模型:
public class MessagePageViewModel : BaseViewModel
{
public ICommand MessageDetailsCommand { get; set; }
INavigation Navigation;
private ObservableCollection<MessageModel> _messagesList;
public ObservableCollection<MessageModel> MessagesList
{
get { return _messagesList; }
set
{
if (_messagesList != value)
{
_messagesList = value;
}
}
}
public ICommand ReloadCommand { get; set; }
public ICommand RefreshCommand
{
get
{
return new Command(async () =>
{
await GetMessages();
Master_PageViewModel vm = new Master_PageViewModel(Navigation,multiMediaPickerService);
await vm.GetCounter();
});
}
}
bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
}
}
public MessagePageViewModel(INavigation navigation)
{
ReloadCommand = new Command(async () => await ReloadPage());
Navigation = navigation;
MessageDetailsCommand = new Command(async (object obj) => await MessageDetails(obj));
Initialize();
}
private async void Initialize()
{
await GetMessages();
}
private async Task ReloadPage()
{
await GetMessages();
}
public async Task GetMessages()
{
List<MessageModel> msg = new List<MessageModel>
.........
MessagesList = new ObservableCollection<MessageModel>(msg);
}
private async Task MessageDetails(object obj)
{
var item = (obj as MessageModel);
await Navigation.PushAsync(new MessageDetailsPage(....));
}
}
}
}
这是因为您在 RefreshCommand
中创建了 Master_PageViewModel
的新实例。它不是父标签页的绑定上下文,因此即使 GetCounter
已被触发,标签的徽章也不会更新。
您必须将父选项卡式视图模型传递给您的 MessagePageViewModel
,例如:
public Master_PageViewModel(INavigation navigation)
{
Navigation = navigation;
messages = new MessagePageViewModel(Navigation, this);
Init();
counter = 0;
}
并更改消息页面视图模型的构造函数:
Master_PageViewModel parentViewModel
public MessagePageViewModel(INavigation navigation, Master_PageViewModel viewModel)
{
ReloadCommand = new Command(async () => await ReloadPage());
Navigation = navigation;
parentViewModel = viewModel;
// ...
}
最后,在刷新命令中触发方法:
public ICommand RefreshCommand
{
get
{
return new Command(async () =>
{
await GetMessages();
await parentViewModel.GetCounter();
});
}
}
此外,我注意到您的 MessagePageViewModel
使用了父选项卡式视图模型的导航。我认为这不是一个好方法,因为它有自己的 NavigationPage,所以它应该使用自己的导航而不是父导航。
我有一个使用标签页的应用程序,在父标签页的 xaml 我填充了所有其他标签页,我有一个视图模型绑定到每个其他标签页的父标签页和视图模型。我在其中一个选项卡上有一个徽章,上面有一个计数器,显示有多少条消息。 我在更新计数器时遇到问题。
所以我有一个调用来从数据库中检索未读消息的数量,这些消息在应用程序加载时填充到计数器中。当我导航查看消息时,它会更新消息已被读取的数据库,然后我使用 popasync 导航回到选项卡式页面,然后我拉动以刷新执行调用以获取已读取消息的数量但它不会更新计数器,如果我在 GetCounter 方法上放置一个断点,我会看到它正在用正确的数量更新计数器,但没有改变徽章。
希望这是有道理的。
如果有人能提供帮助,我将不胜感激。
主标签页:
<NavigationPage Title="Message" Icon="email.png" plugin:TabBadge.BadgeText="{Binding counter}"
plugin:TabBadge.BadgeColor="Red"
plugin:TabBadge.BadgePosition="PositionTopRight"
plugin:TabBadge.BadgeTextColor="Green">
<x:Arguments>
<local:MessagePage BindingContext="{Binding messages}" />
</x:Arguments>
</NavigationPage>
public partial class MasterTabPage : TabbedPage
{
Master_PageViewModel vm;
public MasterTabPage ()
{
InitializeComponent ();
this.BindingContext = vm = new Master_PageViewModel(Navigation);
}
}
主标签页 ViewModel:
public class Master_PageViewModel : INotifyPropertyChanged
{
INavigation Navigation;
private int _counter;
public int counter
{
get => _counter;
set
{
_counter = value;
OnPropertyChanged(nameof(counter));
}
}
public MessagePageViewModel messages { get; set; }
public Master_PageViewModel(INavigation navigation)
{
Navigation = navigation;
messages = new MessagePageViewModel(Navigation);
Init();
counter = 0;
}
public async void Init()
{
await GetCounter();
}
public async Task GetCounter()
{
try
{
using (HttpClient client = new HttpClient())
{
List<MessageModel> msg = new List<MessageModel>();
using (HttpResponseMessage response = await client.GetAsync("http://localhost:53665/api/GetMessagesCount/Id=" + 2 + "/" ))
{
if (response.IsSuccessStatusCode)
{
using (HttpContent content = response.Content)
{
var textresponse = await content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<List<MessageModel>>(textresponse);
foreach (var i in json)
{
msg.Add(new MessageModel
{
msgCounter = i.msgCounter,
});
}
counter = msg[0].msgCounter;
}
}
else
{
}
}
}
}
catch (Exception)
{
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
消息选项卡视图模型:
public class MessagePageViewModel : BaseViewModel
{
public ICommand MessageDetailsCommand { get; set; }
INavigation Navigation;
private ObservableCollection<MessageModel> _messagesList;
public ObservableCollection<MessageModel> MessagesList
{
get { return _messagesList; }
set
{
if (_messagesList != value)
{
_messagesList = value;
}
}
}
public ICommand ReloadCommand { get; set; }
public ICommand RefreshCommand
{
get
{
return new Command(async () =>
{
await GetMessages();
Master_PageViewModel vm = new Master_PageViewModel(Navigation,multiMediaPickerService);
await vm.GetCounter();
});
}
}
bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
}
}
public MessagePageViewModel(INavigation navigation)
{
ReloadCommand = new Command(async () => await ReloadPage());
Navigation = navigation;
MessageDetailsCommand = new Command(async (object obj) => await MessageDetails(obj));
Initialize();
}
private async void Initialize()
{
await GetMessages();
}
private async Task ReloadPage()
{
await GetMessages();
}
public async Task GetMessages()
{
List<MessageModel> msg = new List<MessageModel>
.........
MessagesList = new ObservableCollection<MessageModel>(msg);
}
private async Task MessageDetails(object obj)
{
var item = (obj as MessageModel);
await Navigation.PushAsync(new MessageDetailsPage(....));
}
}
}
}
这是因为您在 RefreshCommand
中创建了 Master_PageViewModel
的新实例。它不是父标签页的绑定上下文,因此即使 GetCounter
已被触发,标签的徽章也不会更新。
您必须将父选项卡式视图模型传递给您的 MessagePageViewModel
,例如:
public Master_PageViewModel(INavigation navigation)
{
Navigation = navigation;
messages = new MessagePageViewModel(Navigation, this);
Init();
counter = 0;
}
并更改消息页面视图模型的构造函数:
Master_PageViewModel parentViewModel
public MessagePageViewModel(INavigation navigation, Master_PageViewModel viewModel)
{
ReloadCommand = new Command(async () => await ReloadPage());
Navigation = navigation;
parentViewModel = viewModel;
// ...
}
最后,在刷新命令中触发方法:
public ICommand RefreshCommand
{
get
{
return new Command(async () =>
{
await GetMessages();
await parentViewModel.GetCounter();
});
}
}
此外,我注意到您的 MessagePageViewModel
使用了父选项卡式视图模型的导航。我认为这不是一个好方法,因为它有自己的 NavigationPage,所以它应该使用自己的导航而不是父导航。