简体   繁体   English

从(不同的)class - Xamarin.Forms 更改 TabbedPage 绑定属性

[英]Changing TabbedPage binding property from a (different) class - Xamarin.Forms

My TabbedPage uses a Binding Property , which is defined in the tabbed page's ViewModel , for showing a Badge text.我的TabbedPage使用在选项卡式页面的ViewModel中定义的Binding Property来显示Badge文本。

I am setting the badge property when initializing the view (actually when it (re)appears).我在初始化视图时设置了 badge 属性(实际上是在它(重新)出现时)。 However, sometimes the badge text is changing from outside of my ViewModel(s), this is because I have a SignalR method which is called when a new message is being added by another application.但是,有时徽章文本会从我的 ViewModel(s) 外部发生变化,这是因为我有一个SignalR方法,当另一个应用程序添加新消息时会调用该方法。

Though, when this happens the OnAppearing method of my tabbed viewmodel is obviously not called.但是,当这种情况发生时,我的选项卡式视图模型的OnAppearing方法显然不会被调用。 So the question is, how can I 'notify' the tabbedpage viewmodel that the badge text should be changed.所以问题是,我如何“通知”标签页视图模型应该更改徽章文本。

I think the (best) way to do this is using somekind of Event.我认为(最好的)方法是使用某种事件。 Since all of my ViewModels inherit from a 'ViewModelBase' I could implement the event notification / change in the ViewModelBase and override the property in my TabbedPage ViewModel.由于我的所有ViewModels都继承自“ViewModelBase”,因此我可以在ViewModelBase中实现事件通知/更改并覆盖我的 TabbedPage ViewModel 中的属性。 Though, sadly my knowledge about using Events / EventArgs is limited and the stuff I found about it is not working.不过,遗憾的是,我对使用Events / EventArgs的了解有限,而且我发现的关于它的东西不起作用。

Is using EventArgs the best way to solve this problem?使用EventArgs是解决此问题的最佳方法吗? And if so, could anyone give any pointers how to implement it properly.如果是这样,任何人都可以提供任何指示如何正确实施它。

*On a side-note, I am also using Prism *附带说明,我也在使用 Prism

My TabbedPage ViewModel:我的标签页视图模型:

public class RootTabbedViewModel : ViewModelBase, IPageLifecycleAware
{
    private readonly INavigationService _navigationService;
    private int _messageCount;

    public RootTabbedViewModel(INavigationService navigationService) 
        : base(navigationService)
    {
        _navigationService = navigationService;
    }


    public int MessageCount
    {
        get { return _messageCount; }
        set { SetProperty(ref _messageCount, value); }
    }

    public void OnDisappearing()
    {
       
    }

    void IPageLifecycleAware.OnAppearing()
    {
        // (omitted) Logic for setting the MessageCount property
    }
}

ViewModelVase:视图模型花瓶:

public class ViewModelBase : BindableBase, IInitialize, IInitializeAsync, INavigationAware, IDestructible, IActiveAware
{
  
    public event EventHandler MessageAddedEventArgs; // this should be used to trigger the MessageCount change.. 
    protected INavigationService NavigationService { get; private set; }

    public ViewModelBase(INavigationService navigationService)
    {
        NavigationService = navigationService;
        Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;

        IsNotConnected = Connectivity.NetworkAccess != NetworkAccess.Internet;
    }

    private bool _isNotConnected;
    public bool IsNotConnected
    {
        get { return _isNotConnected; }
        set { SetProperty(ref _isNotConnected, value); }
    }


    ~ViewModelBase()
    {
        Connectivity.ConnectivityChanged -= Connectivity_ConnectivityChanged;
    }

    async void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
    {
        IsNotConnected = e.NetworkAccess != NetworkAccess.Internet;

        if (IsNotConnected == false)
        {
            await DataHubService.Connect();
        }
    }

    public virtual void Initialize(INavigationParameters parameters)
    {

    }

    public virtual void OnNavigatedFrom(INavigationParameters parameters)
    {

    }

    public virtual void OnNavigatedTo(INavigationParameters parameters)
    {

    }

    public virtual void Destroy()
    {

    }

    public virtual Task InitializeAsync(INavigationParameters parameters)
    {
        return Task.CompletedTask;
    }

}

SignalR Datahub which should trigger the event: SignalR Datahub 应该触发事件:

public static class DataHubService2
{

    // .. omitted some other SignalR specific code
    
    public static async Task Connect()
    {
        try
        {
            GetInstanse();

            hubConnection.On<Messages>("ReceiveMessage", async (message) =>
            {
                if(message != null)
                {
                    // event that message count has changed should be triggered here..
                }
                
            });



        }
        catch (Exception ex)
        {
            // ...
        }

    }

}

As pointed out by @Jason, this specific problem is a good use case for using the MessagingCenter.正如@Jason 所指出的,这个特定问题是使用 MessagingCenter 的一个很好的用例。

In the end the implementation looks as following:最后,实现如下所示:

public static class DataHubService2
{

    // .. omitted some other SignalR specific code
    
    public static async Task Connect()
    {
        try
        {
            GetInstanse();

            hubConnection.On<Messages>("ReceiveMessage", async (message) =>
            {
                if(message != null)
                {
                     MessagingCenter.Send("UpdateMessageCount", "Update");
                }
                
            });



        }
        catch (Exception ex)
        {
            // ...
        }

    }

}


public class RootTabbedViewModel : ViewModelBase, IPageLifecycleAware
{
    private readonly INavigationService _navigationService;
    private int _messageCount;

    public RootTabbedViewModel(INavigationService navigationService) 
        : base(navigationService)
    {
        _navigationService = navigationService;

        MessagingCenter.Subscribe<string>("UpdateMessageCount", "Update", async (a) =>
        {
            await UpdateMessageCount();
        });
    }


    public int MessageCount
    {
        get { return _messageCount; }
        set { SetProperty(ref _messageCount, value); }
    }

    public void OnDisappearing()
    {
    }

    void IPageLifecycleAware.OnAppearing()
    {
        UpdateMessageCount();
    }

    async Task UpdateMessageCount()
    {
        int messageCount = await App.Database.GetNewMessageCountAsync();
        MessageCount = messageCount.ToString();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM