Search code examples
c#xamarinxamarin.formsmvvmxamarin.essentials

Access preferences from different ViewModels


I have SettingsViewModel with:

  public class SettingsViewModel : BaseViewModel, ISettingsViewModel
  {
    public SettingsViewModel()
    {
    }

    private string _gaugeColor;
    public string GaugeColor
    {
      get => Preferences.Get("GaugeColor", "#17805d");
      set
      {
        Preferences.Set("GaugeColor", value);
        this.OnSettingsChanged();
        this.OnPropertyChanged();
      }
    }

    public event EventHandler<SettingsChangedEventArgs> SettingsChanged;
    private void OnSettingsChanged() => this.SettingsChanged?.Invoke(this, new SettingsChangedEventArgs(this.Settings));

    public Settings Settings { get; private set; }
  }
}

I set color by HEX string.

Then in PanelViewModel I have:

private Color _gaugeColor;
public Color GaugeColor
{
  get => Color.FromHex(Preferences.Get("GaugeColor", "#17805d"));
  set
  {
    _gaugeColor = value;
    OnPropertyChanged();
  }
}

Now if I change HEX string from Settings view in UI, color does not change in PanelViewModel until I restart an application. Question is: How to make color change in PanelViewModel right after it has been changed in SettingsViewModel?

I have tried to add this into PanelViewModel, but apparently this creates a new instance of SettingsViewModel and Color does not follow into PanelViewMode. Maybe there is some direct solution and I am using Xamarin.Essentials wrong?

public PanelViewModel()
{
  this.SettingsViewModel = new SettingsViewModel();
  this.SettingsViewModel.SettingsChanged += OnSettingsChanged;
}

private Color _gaugeColor;
public Color GaugeColor
{
  get => Color.FromHex(Preferences.Get("GaugeColor", "#17805d"));
  set
  {
    _gaugeColor = value;
    OnPropertyChanged();
  }
}

private void OnSettingsChanged(object sender, SettingsChangedEventArgs e)
{
  this.GaugeColor = Color.FromHex(e.Settings.GaugeColor);
}

private SettingsViewModel SettingsViewModel { get; }

https://learn.microsoft.com/en-us/dotnet/api/xamarin.essentials.preferences?view=xamarin-essentials


Solution

  • Question is: How to make color change in PanelViewModel right after it has been changed in SettingsViewModel?

    Yes, a simple method is to use MessagingCenter.

    The MessagingCenter class implements the publish-subscribe pattern, allowing message-based communication between components that are inconvenient to link by object and type references. This mechanism allows publishers and subscribers to communicate without having a reference to each other, helping to reduce dependencies between them.

    You can refer to the following code:

    In SettingsViewModel.cs, we can publish a message in the constuctor of it,just as follows:

    public class SettingsViewModel
    {
        public string Title { get; set; }
    
        public SettingsViewModel() {
    
            Title = "SettingsView";
    
            MessagingCenter.Send<Object, Color>(this, "Hi", Color.Yellow);
        }
    
    }
    

    And in PanelViewModel.cs ,we can subscribe to this message:

    public class PanelViewModel
    {
        public string Title { get; set; }
    
        public PanelViewModel() {
    
            Title = "PanelView";
    
             MessagingCenter.Subscribe<Object, Color>(this, "Hi", async (sender, arg) =>
            {
                System.Diagnostics.Debug.WriteLine("----->  receive color= " + arg); 
          
             // here ,we can use the received color to update the UI 
    
            });
        }
    
    }
    

    Note:

    Once we receive the color, we can use the received color to update the UI, and the color field in the PanelViewModel.cs should implement interface INotifyPropertyChanged.