一个 ViewModel 中的触发器 属性 从另一个 ViewModel (MessagingCenter) 更改

Trigger property changed in one ViewModel from another ViewModel (MessagingCenter)

我正在尝试将另一个 ViewModel 的更改通知一个 ViewModel。为此,我尝试使用 MessagingCenter。但是,由于某种原因,它似乎不起作用。有人可以放点灯吗,为什么我无法从一个视图中更改另一个视图中标签的颜色?

HomeViewModel.cs:

using System;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace MessagingCenterApp.ViewModels
{
  public class HomeViewModel : BaseViewModel
  {
    public HomeViewModel()
    {
      Title = "Home";

      MessagingCenter.Subscribe<Object, Color>(this, "gaugeColor", (sender, arg) =>
      {
        this._gaugeColor = arg;
      });

      this.GaugeColor = Color.White;
    }

    private Color _gaugeColor;
    public Color GaugeColor
    {
      get => _gaugeColor;
      set
      {
        _gaugeColor = value;
        OnPropertyChanged();
      }
    }
  }
}

SettingsViewModel.cs:

using MessagingCenterApp.Models;
using MessagingCenterApp.Views;
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace MessagingCenterApp.ViewModels
{
  public class SettingsViewModel : BaseViewModel
  {
    public SettingsViewModel()
    {
      Title = "Settings";
      MessagingCenter.Send<Object, Color>(this, "gaugeColor", Color.FromHex(this.GaugeColor));

    }

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

编辑:

没有单独按钮的实现:

SettingsViewModel.cs:

using MessagingCenterApp.Models;
using MessagingCenterApp.Views;
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace MessagingCenterApp.ViewModels
{
  public class SettingsViewModel : BaseViewModel
  {
    public ICommand changeCommand { get; set; }
    public SettingsViewModel()
    {
      Title = "Settings";

      GaugeColor = Color.Red;

      changeCommand = new Command(changeColor);
    }

    private void changeColor()
    {
      GaugeColor = Color.FromHex(this.GaugeColorS);

      MessagingCenter.Send<Object, Color>(this, "gaugeColor", GaugeColor);
    }

    private Color _gaugeColor;
    public Color GaugeColor
    {
      get => _gaugeColor;
      set
      {
        _gaugeColor = value;
        this.OnPropertyChanged();
      }
    }

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

HomeViewModel.cs:

using System;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace MessagingCenterApp.ViewModels
{
  public class HomeViewModel : BaseViewModel
  {
    public HomeViewModel()
    {
      Title = "Home";

      MessagingCenter.Subscribe<Object, Color>(this, "gaugeColor", (sender, arg) =>
      {

        System.Diagnostics.Debug.WriteLine("received color = " + arg);
        this.GaugeColor = arg;
      });

      this.GaugeColor = Color.Red;
    }

    private Color _gaugeColor;
    public Color GaugeColor
    {
      get => _gaugeColor;
      set
      {
        _gaugeColor = value;
        OnPropertyChanged();
      }
    }
  }
}

如果你想在当前页面属性重置时向另一个页面发送消息,你应该添加一个事件触发器(例如点击[=15=页面中的'Button' ]. 单击按钮后,向页面 HomePage).

发送消息

我简化了你的代码,它在我这边工作正常。您可以修改它以满足您的需要。

BaseViewModel.cs

  public class BaseViewModel : INotifyPropertyChanged
  {
    public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>();

    bool isBusy = false;
    public bool IsBusy
    {
      get { return isBusy; }
      set { SetProperty(ref isBusy, value); }
    }

    string title = string.Empty;
    public string Title
    {
      get { return title; }
      set { SetProperty(ref title, value); }
    }

       public  bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

HomeViewModel.cs

public class HomeViewModel : BaseViewModel
  {

        private Color _gaugeColor;
        public Color GaugeColor
        {
            set { SetProperty(ref _gaugeColor, value); }

            get { return _gaugeColor; }
        }


        public HomeViewModel()
    {
      Title = "Home";

      MessagingCenter.Subscribe<Object, Color>(this, "gaugeColor", (sender, arg) =>
      {

          System.Diagnostics.Debug.WriteLine("received color = " + arg);
           this.GaugeColor = arg;
      });

      this.GaugeColor = Color.Red;
    }

    }

SettingsViewModel.cs

 public class SettingsViewModel : BaseViewModel
  {
    public ICommand changeCommand { get; set; }
    public SettingsViewModel()
    {
      Title = "Settings";

      GaugeColor = Color.Red;

      changeCommand = new Command(changeColor);
    }

        private void changeColor(object obj)
        {
            GaugeColor = Color.Yellow;

            MessagingCenter.Send<Object, Color>(this, "gaugeColor", GaugeColor);
        }

        Color  _gaugeColor;
        public Color GaugeColor
        {
            set { SetProperty(ref _gaugeColor, value); }

            get { return _gaugeColor; }
        }

    }

SettingsPage.xaml(这里我加了Button)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MessagingCenterApp.Views.SettingsPage"
             Title="{Binding Title}"
             xmlns:vm="clr-namespace:MessagingCenterApp.ViewModels" 
             Background="#121212"
             x:Name="BrowseItemsPage">

  <ContentPage.BindingContext>
    <vm:SettingsViewModel />
  </ContentPage.BindingContext>

  <ContentPage.Resources>
    <ResourceDictionary>
      <Color x:Key="Accent">#0d1117</Color>
    </ResourceDictionary>
  </ContentPage.Resources>


    <StackLayout Orientation="Vertical">
      <Label Text="Gauge color:"></Label>
      <Entry Text="{Binding GaugeColor}" Keyboard="Numeric"></Entry>


      <Button  Text="change color"  Command="{Binding changeCommand}"/>
    </StackLayout>

</ContentPage>

更新:

I mean when I type or select new colour on Settings page, I would like to see new colour already

为此,您可以在SettingsViewModel中添加MessagingCenter.Send,如下所示:

    Color  _gaugeColor;
    public Color GaugeColor
    {
        set { 
            
            SetProperty(ref _gaugeColor, value);

            MessagingCenter.Send<Object, Color>(this, "gaugeColor", GaugeColor);
        }

        get { return _gaugeColor; }
    }

如果您不想要按钮,可以删除 SettingsPage.xaml 中的 Button