在xamarin.forms中,如何将同一视图模型的更改通知回到上一页?(可以传递到第二页,但不能回到第二页)



我有两个页面,"主页","设置",包括相同的" myview"(那里的一些选择器(。当我单击主页中的" Go设置"(或显示更多设置(按钮时,值将同步到设置页面。但是,当我在设置页面上单击"应用"时,值不会返回。

我是C#和Xamarin中的新手,并试图在线搜索和Microsoft文档。但是我找不到解决此问题的方法。

我还遵循此链接:如何将多个页面的bindingContext设置为xamarin.forms中的同一viewModel?并在我的代码中执行了相同的全球价值。

  1. myview(contentview(
public MyView()
{
    InitializeComponent();
    BindingContext = GlobalVar.MyViewModel;
    Setting1.SetBinding(Picker.ItemsSourceProperty, "ObList1");
    Setting1.ItemDisplayBinding = new Binding("obj_text");
    Setting1.SetBinding(Picker.SelectedItemProperty, "SelectedItem1");
    //also other pickers
}
  1. 主页(包括myview(
public SearchPage ()
{
    InitializeComponent ();
    BindingContext = GlobalVar.MyViewModel;
}
private async void Click_GoSetting(object sender, EventArgs e)
{
    await Navigation.PushAsync(new SettingPage());
}
  1. 设置页(包括相同的myview(
public partial class SettingPage : ContentPage
{
  MyViewModel viewModel { get; set; } = GlobalVar.MyViewModel;
  public SettingPage ()
  {
    BindingContext = viewModel;
  }
  private async void Click_ApplySetting(object sender, EventArgs e)
  {
    await Navigation.PopAsync(true);
  }
  //some other method deal with viewModel
}
  1. globalvar.cs
        private static  MyViewModel _myViewModel = new MyrViewModel();
        public static MyViewModel MyViewModel
        {
            get
            {
                return _myViewModel;
            }
        }
  1. ViewModel
    public class MyViewModel : BaseViewModel
    {
        public ObservableCollection<obj> ObList1 { get; set; }
        public ObservableCollection<obj> ObList2 { get; set; }
        public ObservableCollection<obj> ObList3 { get; set; }
        public obj SelectedItem1 { get; set; }
        public obj SelectedItem2 { get; set; }
        public obj SelectedItem3 { get; set; }
        public MyViewModel()
        {
            ObList1 = new ObservableCollection<obj>();
            ObList2 = new ObservableCollection<obj>();
            ObList3 = new ObservableCollection<obj>();
        }
    }

也许我应该将设置页面上的更改通知ViewModel?或在ViewModel中的"集合"中做某事?

令人困惑的点是,两个页面使用相同的ViewModel嵌入了相同的视图,但仅通知从第1页到Page2的更改,而不是Page2到Page1。

任何想法,提前提前。

解决方案一:

使用事件可以将值传递回上一页。

在第二页中定义事件:

public delegate void EventHandler(string status);
public event EventHandler EventPass;

页面消失时调用事件:

protected override void OnDisappearing()
{
    base.OnDisappearing();
    EventPass("Back Code");
}

在第一页中,当Naviagtion Place需要在此处添加事件时:

string title = "PageSecondParamater";
PageSecond pageSecond = new PageSecond(title);
pageSecond.EventPass += PageSecond_EventPass; ;
Navigation.PushAsync(pageSecond);

现在的价值将在这里传递:

private void PageSecond_EventPass(string status)
{
    Title = status;
    Console.WriteLine("---" + status);
}

解决方案两个:

使用属性字典在应用程序中存储简易尺寸的数据,当Enter in Page中调用它以获取已存储的数据。

在您要存储数据的第二页中,以波纹管写作:

Application.Current.Properties ["value"] = valuedata;

返回第一页时,覆盖了更新UI的应用方法:

protected override void OnAppearing()
{
    base.OnAppearing();
    if (Application.Current.Properties.ContainsKey("value"))
    {
        var ValueGet = Application.Current.Properties ["value"] as DataType;
        // do something with other things
    }
}

注意: ViewModel如果需要动态更新数据,需要使用InotifyPropertychanged。

示例实现:

public class ObservableProperty : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

ViewModelBase建议将ICommand实施为词典结构,例如:

public abstract class ViewModelBase : ObservableProperty
{
    public Dictionary<string,ICommand> Commands { get; protected set; }
    public ViewModelBase()
    {
        Commands = new Dictionary<string,ICommand>();
    }
}

所以您的ViewModel中的所有todo都只是继承了ViewModelBase类,并使用它:

class LoginViewModel : ViewModelBase
{
    string userName;
    string password;
    public string UserName 
    {
         get {return userName;}
        set 
        {
            userName = value;
            OnPropertyChanged("UserName");
        }
     }
    public string Password 
    {
        get{return password;}
        set
        {
            password = value;
            OnPropertyChanged("Password");
        }
    }
    #endregion
    #region ctor
    public LoginViewModel()
    {
        //Add Commands
        Commands.Add("Login", new Command(CmdLogin));
    }
    #endregion

    #region UI methods
    private void CmdLogin()
    {
        // do your login jobs here
    }
    #endregion
}

已解决。

myViewModel(更新(

    public class MyViewModel : BaseViewModel
    {
        public ObservableCollection<obj> ObList1 { get; set; }
        public ObservableCollection<obj> ObList2 { get; set; }
        public ObservableCollection<obj> ObList3 { get; set; }
        private obj _selectedItem1 = new obj();
        public obj SelectedItem1 
        {
            get { return _selectedItem1; }
            //this is the line solved the problem
            //but still not understood thoroughly
            set { SetProperty(ref _selectedItem1, value); }
        }
        //same for _selectedItem2 _selectedItem3
    }

ps:这里的baseViewModel代码(未更改,从模板代码中更改(

 public class BaseViewModel : INotifyPropertyChanged
    {
        //some other attributes
        //...
        protected bool SetProperty<T>(ref T backingStore, T value,
            [CallerMemberName]string propertyName = "",
            Action onChanged = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingStore, value))
                return false;
            backingStore = value;
            onChanged?.Invoke();
            OnPropertyChanged(propertyName);
            return true;
        }
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;
            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}

看来,通过调用setproperty,也将被撤销。

,但仍然有些困惑,为什么以前的代码像"单向"绑定。

相关内容

  • 没有找到相关文章