我有两个页面,“主页”,“设置页面”,包括相同的“ MyView”(那里有一些选择器)。 当我单击主页上的“转到设置”(或显示更多设置)按钮时,这些值将同步到设置页面。但是,当我在设置页面上单击“应用”时,这些值没有恢复。
我是C#和Xamarin的新手,并尝试搜索在线和Microsoft文档。但是我找不到解决此问题的方法。
我也在关注此链接:How to set BindingContext of multiple pages to the same ViewModel in Xamarin.Forms? 并在我的代码中执行了相同的全局值。
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
}
public SearchPage ()
{
InitializeComponent ();
BindingContext = GlobalVar.MyViewModel;
}
private async void Click_GoSetting(object sender, EventArgs e)
{
await Navigation.PushAsync(new SettingPage());
}
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
}
private static MyViewModel _myViewModel = new MyrViewModel();
public static MyViewModel MyViewModel
{
get
{
return _myViewModel;
}
}
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>();
}
}
也许我应该将我的SettingPage上的更改通知给viewmodel?或在viewmodel的“设置”中做些什么?
令人困惑的一点是,两个页面使用相同的视图模型嵌入相同的视图,但仅通知从Page1到Page2的更改,而不是从Page2到Page1的更改。
任何想法,请提前
答案 0 :(得分:0)
解决方案一:
使用Event可以将值传递回上一页。
在SecondPage中定义事件:
public delegate void EventHandler(string status);
public event EventHandler EventPass;
页面消失时调用事件:
protected override void OnDisappearing()
{
base.OnDisappearing();
EventPass("Back Code");
}
在FirstPage中,当Naviagtion位置需要在此处添加事件时:
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);
}
解决方案二:
使用Properties Dictionary在应用程序中存储简单和小型数据,在进入页面时将调用它以获取已存储的数据。
在第二页上您要存储数据的地方,如下所示:
Application.Current.Properties ["value"] = valuedata;
返回首页时,重写OnAppearing方法以更新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
}
}
注意:如果要动态更新数据,则需要使用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实现为Dictionary结构,例如:
public abstract class ViewModelBase : ObservableProperty
{
public Dictionary<string,ICommand> Commands { get; protected set; }
public ViewModelBase()
{
Commands = new Dictionary<string,ICommand>();
}
}
因此,ViewModel中的所有待办事项都只是继承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
}
答案 1 :(得分:0)
已解决。
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,OnPropertyChanged也将被撤销。
但是对于以前的代码为什么会像“单向”绑定那样仍然有些困惑。