MvvmCross Android Dialog Bing以编程方式 - ViewModel未更新

时间:2013-01-22 15:45:42

标签: binding notifications viewmodel mvvmcross

这是关于MvvmCross Android Dialog Bing Programmatically

的帖子的后续内容

我在Droid项目中实现了Dialog的绑定:

    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绑定中添加了 TwoWay ,仅用于测试目的。

现在的问题是绑定仅在 OneWay 中有效。如果我在视图中更改了某些内容,则 未更新,但如果更改了对象,则会通知视图。这种情况发生在上述两种绑定中(在绑定模式中有或没有 TwoWay )。

这是唯一留下完整Droid.Dialog项目的东西,使用MvvmCross框架处理由viewModel控制的bind和多个视图。

从我能够调试(只有Droid代码而不是PCL,在VS2010中),每当我更改EntryElement中的文本时,都会调用 OnTextChanged 方法并且属性 Value 正在更新。

EntryElement.cs

    public virtual void OnTextChanged(string newText)
    {
        //Log.Info("Just playing","New text:" + newText);
        OnUserValueChanged(newText);
    }

ValueElement.cs

    protected void OnUserValueChanged(TValueType newValue)
    {
        Value = newValue;
        FireValueChanged();
    }

    protected virtual void FireValueChanged()
    {
        var handler = ValueChanged;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

这是我在核心和机器人项目中的代码

CORE

BaseViewModel.cs

    public class BaseViewModel : MvxViewModel, IMvxServiceConsumer
    {
        protected IConfigurationDataStore ConfigDataStore
        {
            get
            {
                if (_configDataStore == null)
                    _configDataStore = this.GetService<IConfigurationDataStore>();

                return _configDataStore;
            }
        }
        private IConfigurationDataStore _configDataStore;
    }

EditConfigurationViewModel.cs

    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);
        }
    }

ConfigurationSet.cs

    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;
    }

DROID

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()
        {

        }
    }

3 个答案:

答案 0 :(得分:2)

https://github.com/zleao/MvvmCross.Dialog

上看到您的回购后的第二个回答

感谢您提供更多信息。

我还没有运行你的样本,但看到重现问题的简单代码有很多帮助。

我认为问题可能在您的安装文件中 - https://github.com/zleao/MvvmCross.Dialog/blob/master/MvvmCross.Dialog.UI.Droid/Setup.cs

其中的设置继承自MvxBaseAndroidBindingSetupCirrious.MvvmCross.Binding.DroidMvxBaseAndroidSetup中所有内容的基本设置类,它本身都来自Cirrious.MvvmCross.Droid的{​​{1}}

由于除了“仅绑定”之外还使用了Dialog代码,因此您需要进一步设置 - 您需要从MvxBaseAndroidDialogBindingSetup添加Cirrious.MvvmCross.Dialog.Droid。此类添加了许多重要步骤,包括在所有Value实例上为ValueElement注册双向绑定 - 请参阅:

    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);
    }
https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Dialog.Droid/MvxBaseAndroidDialogBindingSetup.cs

中的


所以 - 尝试解决问题,尝试从MvxBaseAndroidDialogBindingSetup

继承安装程序

有关MvvmCross图层的详细信息,请参阅http://slodge.blogspot.co.uk/2012/12/a-short-guide-to-layers-of-mvvmcross.html


我希望这有助于解决问题。

感谢您提供优质的细节。

请注意,与Touch Dialog代码相比,Droid.Dialog代码仍然相当年轻 - 因此您可能会遇到真正的错误和问题。当你点击它们时,请在这里提出问题,或者如果它们是错误,那么请在https://github.com/slodge/MvvmCross/issues?state=open

上记录问题

斯图尔特

答案 1 :(得分:1)

我刚刚使用经过修改的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端的Configuration对象是什么?


如果您怀疑这可能是一个错误,那么在https://github.com/slodge/MvvmCross/issues/new上记录这些错误可能最容易

您可以使用错误包含的详细信息越多,就会越快看到 - 例如如果你可以包含一个重现问题的样本github repo,那么开发人员可以快速轻松地进行测试。相反,如果您只是提供说明,那么开发人员可能需要花费1个小时或更长时间进行测试 - 因此您需要等待他们“有空闲时间”。


关于'调试......只有Droid代码而没有PCL,在VS2010'的投诉,请确保你已经用Xamarin提出这个问题 - 他们解决这些问题的唯一方法就是付费用户告诉他们有关问题

答案 2 :(得分:0)

iOS中也需要这样做。

public class Setup : MvxIosDialogSetup//MvxIosSetup