Binding MvvmCross Android对话框以编程方式Bing-ViewModel未更新

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

这是关于

我已经在Droid项目中实现了对话框的绑定:

    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
from
cirior.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中添加了一个回购协议,其中有一个非常简单的示例,我在这里描述了这个示例。()我刚刚用你建议的改变做了测试,现在一切都变了!!!:)我会尽快(希望明天)用更复杂、更完整的方案更新回购协议。谢谢你的帮助!