Forum Xamarin.Forms

Please don't obsolete SetBinding by expression when there is nothing to replace it.

WinterCloudWinterCloud GBMember ✭✭✭
edited July 2017 in Xamarin.Forms

Summary

Currently SetBinding<T> has been labelled as obsolete. This is the only way to bind view to view model, especially complex view model, without magic strings.

API Changes

Don't obsolete? I don't know if there is any changes required in the background.

Examples:

Easy View Model:
Obsolete:

     view.SetBinding<ViewModel>(View.TextProperty, x=>x.Text);     

New way:

     view.SetBinding(View.TextProperty, nameof(ViewModel.Text));     

Complex View Model:
Obsolete:

     view.SetBinding<ViewModel>(View.TextProperty, x=>x.DataModel.Text);     

New way: ???? How to do that without magic strings?

Work around:

    view.SetBinding(View.TextProperty, $"{ nameof(ViewModel.DataModel) }.{ nameof(DataModel.Text) }");

Even more complex View Model:
Obsolete:

     view.SetBinding<ViewModel>(View.TextProperty, x=>x.DataModel.DeeperDataModel.Text);     

New way: ???? How to do that without magic strings?

Work around!?!?:

view.SetBinding(View.TextProperty, $"{ nameof(ViewModel.DataModel) }.{ nameof(DataModel.DeeperDataModel) }.{ nameof(DeeperDataModel.Text) }");

Thanks~.

Tagged:

Open · Last Updated

Posts

  • HunumanHunuman GBMember ✭✭✭✭

    Hi @WinterCloud

    Not sure what you mean by "Magic strings";
    If you mean hard-coded constants, keys, etc. I agree they are best avoided.

    If you mean that a method or property cannot use the name of something to obtain a reference; I would not agree.
    The way I look at it is every time I declare a variable in a high level language, I am creating a "Magic string".

    So I kind a get what you are saying re the usability standpoint, but not the magic string thing.

    Tim

  • VelocityVelocity NZMember ✭✭✭

    Just use nameof instead of magic strings.

  • WinterCloudWinterCloud GBMember ✭✭✭
    edited July 2017

    @Hunuman said:
    Hi @WinterCloud

    Not sure what you mean by "Magic strings";
    If you mean hard-coded constants, keys, etc. I agree they are best avoided.

    If you mean that a method or property cannot use the name of something to obtain a reference; I would not agree.
    The way I look at it is every time I declare a variable in a high level language, I am creating a "Magic string".

    So I kind a get what you are saying re the usability standpoint, but not the magic string thing.

    Tim

    What I mean "Magic strings" is like "MagicStrings" or "Text". They are just strings laying around in code, and when property name or class name changes, they are easily forgotten to change as well, there might be a lot of them if not careful.

  • WinterCloudWinterCloud GBMember ✭✭✭

    @Velocity said:
    Just use nameof instead of magic strings.

    I provided some examples in the thread starter, nameof() doesn't work with complex view models, have to use $"{}.{}" as a work around, and this work around can get really messy.

  • HunumanHunuman GBMember ✭✭✭✭

    @WinterCloud said:

    What I mean "Magic strings" is like "MagicStrings" or "Text". They are just strings laying around in code, and when property name or class name changes, they are easily forgotten to change as well, there might be a lot of them if not careful.

    Hi @WinterCloud

    Thank you for the clarification.

    By that definition nameof usage is not a magic string, since it getting the actual instance name, IMO
    But I stick by my original position - code is simply purposely grouped magic strings that a complier processes to help decide the actual implementation it produces.

    Probably best if we agree to disagree on this one.

    All the best,

    Tim

  • WinterCloudWinterCloud GBMember ✭✭✭

    @Hunuman said:

    @WinterCloud said:

    What I mean "Magic strings" is like "MagicStrings" or "Text". They are just strings laying around in code, and when property name or class name changes, they are easily forgotten to change as well, there might be a lot of them if not careful.

    Hi @WinterCloud

    Thank you for the clarification.

    By that definition nameof usage is not a magic string, since it getting the actual instance name, IMO
    But I stick by my original position - code is simply purposely grouped magic strings that a complier processes to help decide the actual implementation it produces.

    Probably best if we agree to disagree on this one.

    All the best,

    Tim

    No, I don't think nameof usage is magic strings, I agree with you on this, because they are getting compiled, when property or class name changes, nameof will have to change as well to avoid build error.

    The topic is about when there are complex view models, a simple nameof will not work, and currently I have to rely on that work around, which is half strings half nameof, really messy to maintain.

  • HunumanHunuman GBMember ✭✭✭✭

    @WinterCloud

    Sorry I wasn't looking to go off topic, I was simply looking for clarification.

    Hope this proposal works out for you, I certainly have no objection either way.

    Tim

  • JoeMankeJoeManke USMember ✭✭✭✭✭
    edited July 2017

    I would recommend either simplifying your ViewModels or take advantage of the fact that BindingContext is itself a BindableProperty.

    view.SetBinding(View.BindingContextProperty, nameof(ViewModel.DataModel));
    view.SetBinding(View.TextProperty, nameof(DataModel.Text));
    
  • ThereIsNoUsernameThereIsNoUsername USMember ✭✭

    Methods should not use string as a datatype for a parameter unless the parameter actually is a string.
    The data type string should ONLY be used to store text that has no functional meaning or relevance to the functionality of the application (code).

    In this case, the method SetBinding has two parameters:
    1. targetProperty of type BindableProperty, which is a real and proper type.
    2. path of type string, which is a "generic" type, intended to be used to store text for human consumption (read).

    In this particular case, I would create an interface along with a standard/default non-sealed implementation of that interface, and use that interface as the type for the second parameter.
    This gives these possibilities:
    1. Easy use for the simple cases by using the the default implementation of the interface
    2. Possibility to extend the functionality and override features of the default implementation by inheriting from it.
    3. Full customization and integration with existing code and models, as well as allowing for very advanced scenarios by implementing the interface wherever and in whatever way is needed for the advanced and complex scenario.

    And again, only use strings for storing text that should be displayed and read by a human, everywhere else one should use real types designed for the data they represent.

  • HunumanHunuman GBMember ✭✭✭✭
    edited July 2017

    Hi @ThereIsNoUsername

    I get where you are coming from but looking at it pragmatically I disagree.
    Strongly typed data values and loosely typed values are both important parts of the developers toolkit.

    Loose typing is at the heart of lovely things like XML and HTML, REST , etc.,

    Tim

    PS Welcome to the forums.

  • ThereIsNoUsernameThereIsNoUsername USMember ✭✭

    XML, HTML, and REST are all designed to transfer data between system where you don't have full control of all endpoints. In those scenarios it might have some merits, but we are now talking about .NET, a strongly typed development framework where the main development language is C#, a strongly typed language. One of the main design goals with .NET and C# is to provide an environment where it is difficult to make mistakes, and to maximize developer productivity.
    Great care has been taken in many aspects of both .NET and C# to make sure it promotes the use of a strongly typed framework.

    There is a reason Microsoft invented and put all the resources into developing TypeScript, so please check with internal gurus like Anders Hejlsberg on important design decisions like this.

    Some good reading
    Static Typing Where Possible, Dynamic Typing When Needed:
    The End of the Cold War Between Programming Languages
    Erik Meijer and Peter Drayton
    Microsoft Corporation
    https://www.ics.uci.edu/~lopes/teaching/inf212W12/readings/rdl04meijer.pdf

  • HunumanHunuman GBMember ✭✭✭✭

    Hi @ThereIsNoUsername

    Like I said I get where you are coming from but looking at it pragmatically I disagree.
    If you feel that statement is unreasonable it is probably best to agree to disagree on this one.

    Tim

  • ChaseFlorellChaseFlorell CAInsider, University mod

    @JoeManke said:
    I would recommend either simplifying your ViewModels or take advantage of the fact that BindingContext is itself a BindableProperty.

    view.SetBinding(View.BindingContextProperty, nameof(ViewModel.DataModel));
    view.SetBinding(View.TextProperty, nameof(DataModel.Text));
    

    This

  • RobertDurfeeRobertDurfee USMember ✭✭

    These were marked obsolete a few releases ago for performance reasons. I remember Xamarin saying do not use them.

  • ThereIsNoUsernameThereIsNoUsername USMember ✭✭

    I'm quite sure that starting to parse strings is not the correct way to go for optimal performance...

    Before Microsoft bought Skype, they had an API that basically was one method with a string parameter. You could use it for everything, as long as your formatted the string correctly...I wonder why the no longer use that API.... ;)

  • RobertDurfeeRobertDurfee USMember ✭✭

    It's not simply the performance of "parsing strings". That version of the API comes with a large performance and app size penalty on iOS. It was deprecated in Xamarin.Forms 2.1.

    https://forums.xamarin.com/discussion/comment/178701/#Comment_178701

  • ThereIsNoUsernameThereIsNoUsername USMember ✭✭

    It might be so, but the solution should not be to use an API that is error prone, without type checking and were Roslyn and other tool are unable to determine what is going on and if the arguments used to call the method are correct or not.

  • WinterCloudWinterCloud GBMember ✭✭✭

    @RobertDurfee said:
    It's not simply the performance of "parsing strings". That version of the API comes with a large performance and app size penalty on iOS. It was deprecated in Xamarin.Forms 2.1.

    https://forums.xamarin.com/discussion/comment/178701/#Comment_178701

    I thought that's for creating Bindable Properties only? It's not? :s

    What about Linq expressions? And command creating actions? Are they all have a heavy price on iOS?

  • WinterCloudWinterCloud GBMember ✭✭✭

    @JoeManke said:
    I would recommend either simplifying your ViewModels or take advantage of the fact that BindingContext is itself a BindableProperty.

    view.SetBinding(View.BindingContextProperty, nameof(ViewModel.DataModel));
    view.SetBinding(View.TextProperty, nameof(DataModel.Text));
    

    Great, I'm already using this way to build my views and view models, to save repeated set bindings, that's why I have view models under view models.

    The problem only raise when I want to share a few things between the view models, it became very complicated without using magic strings.

  • DavidDancyDavidDancy AUMember ✭✭✭✭

    @WinterCloud I've always taken the view that "normalized" data belongs in the Model part of the code, but for ViewModels I've "denormalized" the Models into much flatter objects. There's a slight penalty in transitioning between the two formats, but it has been easier to think about a single Page paired with a single ViewModel, with the minimum data required to fill the screen, than to make everything as fully generic as possible. I sympathise with what you're trying to do, but pragmatically it has been easier to take one approach for Models and a different approach for ViewModels. Then bindings between ViewModels and Page objects are really simple.

    However I do support your suggestion here, but for different reasons. The expression-based bindings were originally deprecated because they ended up making the app's code bigger, but there are some of us who aren't as concerned with that problem as others are. Perhaps we're making corporate apps that get distributed over WiFi or are never uploaded to the stores, and we don't see the size issue as a problem. So it would be nice to have the choice without being threatened with the deprecation.

    In addition, the fact that expression-based bindings make the code bigger is a compiler problem that should be handed off to the compiler team to see if they can do anything about it. If I were a compiler person I'd be very interested in that kind of problem because I could see wide applications for it if any solution were to be found.

Sign In or Register to comment.