Desired Result
- A status bar at the top of most xaml pages, of which the colour and text change depending on the value of a boolean variable.
- The page background is also set to a colour based on this boolean.
- Essentially these signify whether the app is connected to the server; we don't need to discuss connectivity logic here, apart from a method which inverts the "online" boolean, so as to simulate changing connectivity status and to test the bindings.
- I want these to update without repeated logic in every view model.
Current Implementation
To try and minimise the amount of code, I will try to reduce the project into four files, and also only concern ourselves with the text property (if we can get text working, we can get colour working too). Hopefully we can assume my ViewModelLocator.cs, App.xaml, Generic.xaml and the supporting ConnectivityStatusBar.cs have been correctly implemented (I can share these too if necessary).
- HomePage.xaml: An example view which utilises the connectivity status bar.
<Page
x:Class="Client.View.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:customElements="using:Client.CustomElements"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource ViewModelLocator}}">
<Grid>
<StackPanel>
<customElements:ConnectivityStatusBar
Text="{Binding ConnectivityStatusBar.Text,
Source={StaticResource ViewModelLocator}}" />
<Button Content="Invert"
Command="{Binding HomePage.InvertConnectivityCommand}" />
</StackPanel>
</Grid>
</Page>
- SessionData.cs: Where the connectivity boolean is found, I have tried setting the class up like a singleton.
using Client.ViewModel;
using GalaSoft.MvvmLight;
namespace Client
{
public sealed class SessionData : ViewModelBase
{
private static readonly SessionData Instance = new SessionData();
private bool _online;
public static SessionData getInstance
{
get { return Instance; }
}
public bool Online
{
get { return _online; }
set
{
_online = value;
RaisePropertyChanged(() => Online);
RaisePropertyChanged(() => ConnectivityStatusBarViewModel.getInstance.Text);
}
}
}
}
- ConnectivityStatusBarViewModel.cs: Logic deciding what the colour and text for the status bar should be. I have attempted similar singleton logic here.
using System;
using GalaSoft.MvvmLight;
namespace Client.ViewModel
{
public sealed class ConnectivityStatusBarViewModel : ViewModelBase
{
private static readonly ConnectivityStatusBarViewModel Instance = new ConnectivityStatusBarViewModel();
public static ConnectivityStatusBarViewModel getInstance
{
get { return Instance; }
}
public String Text
{
get { return SessionData.getInstance.Online ? "Online" : "Offline"; }
}
}
}
- HomePageViewModel.cs: Where the boolean inversion method is found.
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
namespace Client.ViewModel
{
public class HomePageViewModel : ViewModelBase
{
public HomePageViewModel()
{
InvertConnectivityCommand = new RelayCommand(InvertConnectivity);
}
public RelayCommand InvertConnectivityCommand { get; set; }
private void InvertConnectivity()
{
SessionData.getInstance.Online = !SessionData.getInstance.Online;
}
}
}
This code doesn't give me the results I want; when the button is pressed on HomePage.xaml, the text does not change. It does work if I put the inversion method into ConnectivityStatusBarViewModel.cs.
Is it possible to make this work, or am I wasting my time? If it is possible, how can I change my approach to make it work?
Edit: ViewModelLocator.cs looks like:
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
namespace Client.ViewModel
{
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<ConnectivityStatusBarViewModel>();
SimpleIoc.Default.Register<HomePageViewModel>();
}
public ConnectivityStatusBarViewModel ConnectivityStatusBar
{
get { return ServiceLocator.Current.GetInstance<ConnectivityStatusBarViewModel>(); }
}
public HomePageViewModel HomePage
{
get { return ServiceLocator.Current.GetInstance<HomePageViewModel>(); }
}
}
}