Binding MvvmCross Android对话框以编程方式Bing-ViewModel未更新
这是关于 我已经在Droid项目中实现了对话框的绑定:Binding MvvmCross Android对话框以编程方式Bing-ViewModel未更新,binding,notifications,viewmodel,mvvmcross,Binding,Notifications,Viewmodel,Mvvmcross,这是关于 我已经在Droid项目中实现了对话框的绑定: this.Root = new RootElement("Customer Info") { new Section("Private Configuration") { new EntryElement("Pin:").Bind(this, "{'Value':{'Path':'Configuration.Pin'}}"), new Entry
this.Root = new RootElement("Customer Info")
{
new Section("Private Configuration")
{
new EntryElement("Pin:").Bind(this, "{'Value':{'Path':'Configuration.Pin'}}"),
new EntryElement("Name:").Bind(this, "{'Value':{'Path':'Configuration.Name', 'Mode':'TwoWay'}}"),
};
};
我在Configuration.Name
bind中添加了双向功能,仅用于测试目的
现在的问题是绑定只能以一种方式工作。如果我在视图中更改了某些内容,则对象不会更新,但如果对象更改,则会通知视图。这在上面描述的两个绑定中都会发生(在绑定模式中有或没有双向)
这是唯一一个完整的Droid.Dialog项目,使用绑定和多视图,由viewModels控制,使用MvvmCross框架
根据我调试的结果(在VS2010中,只有Droid代码,没有PCL),每次我更改EntryElement
中的文本时,都会调用OnTextChanged方法并更新属性值
EntryElement.cs
ValueElement.cs
这是我在核心和droid项目中的代码
核心
BaseViewModel.cs
public class BaseViewModel : MvxViewModel, IMvxServiceConsumer
{
protected IConfigurationDataStore ConfigDataStore
{
get
{
if (_configDataStore == null)
_configDataStore = this.GetService<IConfigurationDataStore>();
return _configDataStore;
}
}
private IConfigurationDataStore _configDataStore;
}
public class EditConfigurationViewModel : BaseViewModel, IEditConfigurationViewModel
{
public ConfigurationSet Configuration
{
get { return _configuration; }
set
{
if (_configuration != value)
{
_configuration = value;
RaisePropertyChanged(() => Configuration);
}
}
}
private ConfigurationSet _configuration;
public EditConfigurationViewModel(string id)
{
Guid value;
if (string.IsNullOrEmpty(id) || !Guid.TryParse(id, out value))
{
Configuration = new ConfigurationSet();
}
else
{
Configuration = ConfigDataStore.GetConfiguration(value);
}
}
public void SaveConfiguration()
{
ConfigDataStore.UpdateConfiguration(Configuration);
}
}
public class ConfigurationSet : MvxNotifyPropertyChanged
{
public string Pin
{
get { return _pin; }
set
{
if (_pin != value)
{
_pin = value;
RaisePropertyChanged(() => Pin);
}
}
}
private string _pin;
public string Name
{
get { return _name; }
set
{
//if (_name != value)
//{
_name = value;
RaisePropertyChanged(()=> Name);
//}
}
}
private string _name;
public string PrivateDescription
{
get { return _privateDescription; }
set
{
if (_privateDescription != value)
{
_privateDescription = value;
RaisePropertyChanged(() => PrivateDescription);
}
}
}
private string _privateDescription;
}
ConfigurationSet.cs
public class BaseViewModel : MvxViewModel, IMvxServiceConsumer
{
protected IConfigurationDataStore ConfigDataStore
{
get
{
if (_configDataStore == null)
_configDataStore = this.GetService<IConfigurationDataStore>();
return _configDataStore;
}
}
private IConfigurationDataStore _configDataStore;
}
public class EditConfigurationViewModel : BaseViewModel, IEditConfigurationViewModel
{
public ConfigurationSet Configuration
{
get { return _configuration; }
set
{
if (_configuration != value)
{
_configuration = value;
RaisePropertyChanged(() => Configuration);
}
}
}
private ConfigurationSet _configuration;
public EditConfigurationViewModel(string id)
{
Guid value;
if (string.IsNullOrEmpty(id) || !Guid.TryParse(id, out value))
{
Configuration = new ConfigurationSet();
}
else
{
Configuration = ConfigDataStore.GetConfiguration(value);
}
}
public void SaveConfiguration()
{
ConfigDataStore.UpdateConfiguration(Configuration);
}
}
public class ConfigurationSet : MvxNotifyPropertyChanged
{
public string Pin
{
get { return _pin; }
set
{
if (_pin != value)
{
_pin = value;
RaisePropertyChanged(() => Pin);
}
}
}
private string _pin;
public string Name
{
get { return _name; }
set
{
//if (_name != value)
//{
_name = value;
RaisePropertyChanged(()=> Name);
//}
}
}
private string _name;
public string PrivateDescription
{
get { return _privateDescription; }
set
{
if (_privateDescription != value)
{
_privateDescription = value;
RaisePropertyChanged(() => PrivateDescription);
}
}
}
private string _privateDescription;
}
机器人
EditConfigurationView
public class EditConfigurationView : MvxBindingDialogActivityView<EditConfigurationViewModel>, IMvxServiceConsumer
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
DroidResources.Initialise(typeof(Resource.Layout));
Root = new RootElement()
{
new Section("Private Configuration")
{
new EntryElement("Pin:").Bind(this, "{'Value':{'Path':'Configuration.Pin'}}"),
new EntryElement("Name:").Bind(this, "{'Value':{'Path':'Configuration.Name'}}"),
new EntryElement("Description:").Bind(this, "{'Value':{'Path':'Configuration.PrivateDescription'}}")
}
};
}
public override void OnBackPressed()
{
ViewModel.SaveConfiguration();
base.OnBackPressed();
}
protected override void OnViewModelSet()
{
}
}
公共类编辑配置视图:MvxBindingDialogActivityView,IMvxServiceConsumer
{
创建时受保护的覆盖无效(捆绑包)
{
base.OnCreate(bundle);
DroidResources.Initialise(typeof(Resource.Layout));
Root=新的RootElement()
{
新章节(“专用配置”)
{
新的EntryElement(“Pin:”).Bind(这个“{'Value':{'Path':'Configuration.Pin'}”),
新EntryElement(“Name:”).Bind(此“{'Value':{'Path':'Configuration.Name'}”),
新的EntryElement(“Description:”).Bind(这个“{'Value':{'Path':'Configuration.PrivateDescription'}”)
}
};
}
public override void OnBackPressed()
{
ViewModel.SaveConfiguration();
base.OnBackPressed();
}
受保护的覆盖无效OnViewModelSet()
{
}
}
我刚刚用一个修改过的CustomerManagement示例应用程序测试了这一点,这个绑定对我来说是双向的
我的代码:
Root = new RootElement()
{
new Section("Customer Info")
{
new EntryElement("Name").Bind(this, "{'Value':{'Path':'Customer.Name'}}"),
new EntryElement("Website").Bind(this, "{'Value':{'Path':'Customer.Website'}}"),
new EntryElement("Phone").Bind(this, "{'Value':{'Path':'Customer.PrimaryPhone'}}"),
}
};
我的ViewModel和Customer对象是:
public abstract class BaseEditCustomerViewModel
: BaseViewModel
{
private Customer _customer;
public Customer Customer
{
get { return _customer; }
private set { _customer = value; RaisePropertyChanged("Customer"); }
}
// ...
}
public class Customer : MvxNotifyPropertyChanged
{
public Customer()
{
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; RaisePropertyChanged("Name"); }
}
private string _website;
public string Website
{
get { return _website; }
set { _website = value; RaisePropertyChanged("Website"); }
}
private string _primaryPhone;
public string PrimaryPhone
{
get { return _primaryPhone; }
set { _primaryPhone = value; RaisePropertyChanged("PrimaryPhone"); }
}
// ...
}
从您的描述中,我没有发现任何明显的错误-尽管我显然看不到所有细节-例如,ViewModel端的配置对象是什么
如果您怀疑这可能是一个bug,那么登录这些bug可能是最简单的方法 你可以在bug中包含的细节越多,它就越容易被发现——例如,如果你可以包含一个重现问题的github repo示例,那么开发人员就可以快速、轻松地进行测试。相反,如果您只是提供指令,那么开发人员可能需要1个或更多小时来进行测试——因此您需要等待他们有“空闲时间”
关于“调试”的投诉。。。在VS2010'中,只有Droid代码,没有PCL,请确保您已向Xamarin提出此问题-他们解决这些问题的唯一方法是,如果有付费客户告诉他们有关问题。看到您的回购协议后,第二个答案是
谢谢你的补充信息 我还没有运行您的示例,但是看到重现问题的简单代码会有很大帮助 我认为问题可能出在您的安装文件中- 那里的设置继承自
MvxBaseAndroidBindingSetup
,它是cirior.MvvmCross.Binding.Droid中所有内容的基本设置类,并且它本身继承自MvxBaseAndroidSetup
fromcirior.MvvmCross.Droid
由于除了“仅绑定”之外,您还使用了对话框代码,因此您需要进一步进行设置-您需要从cirrial.MvvmCross.Dialog.Droid
添加MvxBaseAndroidDialogBindingSetup
。此类添加了许多重要步骤,包括在所有ValueElement
实例上注册Value
的双向绑定-请参阅:
protected override void FillTargetFactories(
Cirrious.MvvmCross.Binding.Interfaces.Bindings.Target.Construction.IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterFactory(new MvxPropertyInfoTargetBindingFactory(typeof (ValueElement), "Value",
(element, propertyInfo) =>
new MvxElementValueTargetBinding(element,
propertyInfo)));
base.FillTargetFactories(registry);
}
在
因此-若要尝试解决此问题,请尝试从MvxBaseAndroidDialogBindingSetup
有关MvvmCross各层的更多信息,请参阅
我希望这有助于解决问题
感谢您提供的出色细节
不过,请注意,Droid.Dialog代码与Touch Dialog代码相比仍然很年轻,因此您可能会遇到真正的bug和问题。当你们点击它们时,请在这里提问,或者如果它们是bug,请将它们登录到问题页面
Stuart这在iOS中也是必需的
public class Setup : MvxIosDialogSetup//MvxIosSetup
我已经编辑了这个问题,并在“Core”和“Droid”项目中添加了代码。我将准备一个样本放入GitHub回购。ThanksI在GitHub中添加了一个回购协议,其中有一个非常简单的示例,我在这里描述了这个示例。()我刚刚用你建议的改变做了测试,现在一切都变了!!!:)我会尽快(希望明天)用更复杂、更完整的方案更新回购协议。谢谢你的帮助!