How to do CreateBindingSet() on Windows Phone?

杀马特。学长 韩版系。学妹 提交于 2019-12-10 10:03:49

问题


In the N+1 video #34 (Progress), there was an example of using CreateBindingSet() for the Android version, which is not typical. But the narrator also mentioned briefly that the same can be done on the Windows platform.

As much as I tried, however, I am unable to get a View's property to be bound to its ModelView on the Windows Phone. I always get a NullReferenceException.

The closest I came was the code below, including suggestions from ReSharper. Here's my FirstView.xaml.cs:

using Cirrious.MvvmCross.Binding.BindingContext;
using Whatever.ViewModels;

namespace Whatever {

// inheriting from IMvxBindingContextOwner was suggested by ReSharper also

public partial class FirstView : BaseView, IMvxBindingContextOwner {

  public class MyBindableMediaElement
  {
        private string _theMediaSource = "whatever";                                                                                                                     
        public string TheMediaSource
        {
            get
            {
                return _theMediaSource;
            }
            set
            {
                _theMediaSource = value;
            }
        }
   }

  public FirstView()
   {
        InitializeComponent();

        _mediaElement = new MyBindableMediaElement(this.theMediaElement);

        var set = this.CreateBindingSet<FirstView, FirstViewModel>();
        // the corresponding view model has a .SongToPlay property with get/set defined
        set.Bind(_mediaElement).For(v => v.TheMediaSource).To(vm => vm.SongToPlay);
        set.Apply();
   }

    public IMvxBindingContext BindingContext { get; set; }      // this was suggested by ReSharper
}

I get a NullReferenceException in MvxBaseFluentBindingDescription.cs as soon as the view is created. The exact location is below:

    protected static string TargetPropertyName(Expression<Func<TTarget, object>> targetPropertyPath)
    {
        var parser = MvxBindingSingletonCache.Instance.PropertyExpressionParser;        // <----- exception here**
        var targetPropertyName = parser.Parse(targetPropertyPath).Print();
        return targetPropertyName;
    }

I have not seen a working example of creating a binding set on a Windows Phone emulator. Has anyone gotten this to work? Thanks.


回答1:


I can confirm that the narrator said that remark a little too flippantly without actually thinking about how he might do it...

However, with a little effort, you definitely can get the CreateBindingSet to work in Windows if you want to.

Before you start, do consider some alternatives - in particular, I suspect most people will use either Windows DependencyProperty binding or some hand-crafted code-behind with a PropertyChanged event subscription.

If you do want to add CreateBindingSet code to a Windows project then:

  1. Add the Binding and BindingEx assemblies to your Ui project - the easiest way to do this is using nuget to add the BindingEx package.
  2. In your Setup class, override InitializeLastChance and use this opportunity to create a MvxWindowsBindingBuilder instance and to call DoRegistration on that builder. Both these first two steps are covered in the n=35 Tibet binding video - and it's this second step that will initialise the binding framework and help you get past your current 'NullReferenceException' (for the code, see BindMe.Store/Setup.cs)
  3. In your view, you'll need to implement the IMvxBindingContextOwner interface and you'll need to ensure the binding context gets created. You should be able to do this as simply as BindingContext = new MvxBindingContext();
  4. In your view, you'll need to make sure the binding context is given the same DataContext (view model) as the windows DataContext. For a Phone Page, the easiest way to do this is probably just to add BindingContext.DataContext = this.ViewModel; to the end of your phone page's OnNavigatedTo method. Both steps 3 and 4 could go in your BaseView if you intend to use Mvx Binding in other classes too.
  5. With this done, you should be able to use the CreateBindingSet code - although do make sure that all binding is done after the new MvxBindingContext() has been created.

I've not got a windows machine with me right now so I'm afraid this answer code comes untested - please do post again if it does or doesn't work.




回答2:


I can confirm it works almost perfectly; the only problem is, there are no defaults register, so one has to do the full binding like:

set.Bind(PageText).For(c => c.Text).To(vm => vm.Contents.PageText).OneTime();

to fix this, instead of registering MvxWindowsBindingBuilder, I am registering the following class. Note: I have just created this class, and needs testing.

public class UpdatedMvxWindowsBindingBuilder : MvxWindowsBindingBuilder
{
    protected override void FillDefaultBindingNames(IMvxBindingNameRegistry registry)
    {
        base.FillDefaultBindingNames(registry);



        registry.AddOrOverwrite(typeof(Button), "Command");
        registry.AddOrOverwrite(typeof(HyperlinkButton), "Command");
        //registry.AddOrOverwrite(typeof(UIBarButtonItem), "Clicked");

        //registry.AddOrOverwrite(typeof(UISearchBar), "Text");
        //registry.AddOrOverwrite(typeof(UITextField), "Text");
        registry.AddOrOverwrite(typeof(TextBlock), "Text");
        //registry.AddOrOverwrite(typeof(UILabel), "Text");
        //registry.AddOrOverwrite(typeof(MvxCollectionViewSource), "ItemsSource");
        //registry.AddOrOverwrite(typeof(MvxTableViewSource), "ItemsSource");
        //registry.AddOrOverwrite(typeof(MvxImageView), "ImageUrl");
        //registry.AddOrOverwrite(typeof(UIImageView), "Image");
        //registry.AddOrOverwrite(typeof(UIDatePicker), "Date");
        //registry.AddOrOverwrite(typeof(UISlider), "Value");
        //registry.AddOrOverwrite(typeof(UISwitch), "On");
        //registry.AddOrOverwrite(typeof(UIProgressView), "Progress");
        //registry.AddOrOverwrite(typeof(IMvxImageHelper<UIImage>), "ImageUrl");
        //registry.AddOrOverwrite(typeof(MvxImageViewLoader), "ImageUrl");

        //if (_fillBindingNamesAction != null)
        //  _fillBindingNamesAction(registry);
    }       
}

This is a skeleton from Touch binding, and so far I have only updated three controls to test out (Button, HyperButton and TextBlock)



来源:https://stackoverflow.com/questions/18115240/how-to-do-createbindingset-on-windows-phone

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!