Home>

I am studying Xamarin.

I have implemented a ViewModel that displays dynamically changing values ​​in the view with data binding.
There are many properties, and the situation is as follows.

private string _xAccel;
        public string xAccel
        {
            get {return _xAccel;}
            set
            {
                _xAccel = value;
                OnPropertyChanged ("xAccel");
            }
        }
        private string _yAccel;
        public string yAccel
        {
            get {return _yAccel;}
            set
            {
                _yAccel = value;
                OnPropertyChanged ("yAccel");
            }
        }
        private string _zAccel;
        public string zAccel
        {
            get {return _zAccel;}
            set
            {
                _zAccel = value;
                OnPropertyChanged ("zAccel");
            }
        }
        private string _xHoge;
        public string xHoge
        {
            get {return _xHoge;}
            set
            {
                _xHoge = value;
                OnPropertyChanged ("xHoge");
            }
        }
///////////////////// Omitted /////////////////////


ViewModel inherits a base class that provides an implementation of INotifyPropertyChanged.
Accel is an accelerometer, but if this increases with gyro, compass, GPS, etc., the code will be enlarged only by the property, so I want to put it together in sensor units, what should I do?

Addition after BA selection

I asked this question and taught you various implementation methods. The discussion of MVVM policy was also discussed, but first of all, we adopted the method of describing in VM by using the method using Fody and putting it together with #region.
I'm glad to ask you a question. Thank you very much.

  • Answer # 1

    The question is "I want to put together the properties", but if you look at the comments after that, it seems as long as the description of the properties is simple.
    In addition, the property is not something special processing, but only regular things are lined up, so I thought that it would be most in line with the intention if it could be processed in a loop.

    A text template can be used for any number of properties.
    However, since completion cannot be used, I think that it should be a partial class with a separate file from the main source. This allows you to divide a class into multiple files.

    <# @ template debug = "false" hostspecific = "false" language = "C #" #>
    <# @ assembly name = "System.Core" #>
    <# @ import namespace = "System.Linq" #>
    <# @ import namespace = "System.Text" #>
    <# @ import namespace = "System.Collections.Generic" #>
    <# @ output extension = ". cs" #>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace ConsoleApp1
    {
        public partial class Class1
        {
    <#
    var names = new string []
    {
        "xAccel", "yAccel", "zAccel", "xHoge"
    };
    foreach (var name in names)
    {
    #>
            private string _<# = name #> ;;
            public string<# = name #>
            {
                get =>_<# = name #> ;;
                set
                {
                    if (value == _<# = name #>) return;
                    _<# = name #>= value;
                    OnPropertyChanged ("<# = name #>");
                }
            }
    <#
    }
    #>
        }
    }

    The text template is described above.
    When the property increases, increase the name element.
    Saving this will automatically generate cs expanded as follows:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace ConsoleApp1
    {
        public partial class Class1
        {
            private string _xAccel;
            public string xAccel
            {
                get =>_xAccel;
                set
                {
                    if (value == _xAccel) return;
                    _xAccel = value;
                    OnPropertyChanged ("xAccel");
                }
            }
            private string _yAccel;
            public string yAccel
            {
                get =>_yAccel;
                set
                {
                    if (value == _yAccel) return;
                    _yAccel = value;
                    OnPropertyChanged ("yAccel");
                }
            }
            private string _zAccel;
            public string zAccel
            {
                get =>_zAccel;
                set
                {
                    if (value == _zAccel) return;
                    _zAccel = value;
                    OnPropertyChanged ("zAccel");
                }
            }
            private string _xHoge;
            public string xHoge
            {
                get =>_xHoge;
                set
                {
                    if (value == _xHoge) return;_xHoge = value;
                    OnPropertyChanged ("xHoge");
                }
            }
        }
    }
    Additional

    When specifying a type as well as a property name

    <# @ template debug = "false" hostspecific = "false" language = "C #" #>
    <# @ assembly name = "System.Core" #>
    <# @ import namespace = "System.Linq" #>
    <# @ import namespace = "System.Text" #>
    <# @ import namespace = "System.Collections.Generic" #>
    <# @ output extension = ". cs" #>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace ConsoleApp1
    {
        public partial class Class1
        {
    <#
    var properties = new []
    {
        new {Name = "xAccell", Type = "string"},
        new {Name = "yAccell", Type = "string"},
        new {Name = "zAccell", Type = "string"},
        new {Name = "xHoge", Type = "string"},
    };
    foreach (var property in properties)
    {
    #>
            private<# = property.Type #>_<# = property.Name #> ;;
            public<# = property.Type #><# = property.Name #>
            {
                get =>_<# = property.Name #> ;;
                set
                {
                    if (value == _<# = property.Name #>) return;
                    _<# = property.Name #>= value;
                    OnPropertyChanged ("<# = property.Name #>");
                }
            }
    <#
    }
    #>
        }
    }

  • Answer # 2

    There are some countermeasures, but one of the following may simplify the implementation method.

    Use ReactiveProperty

    Use PropertyChanged.Fody

    If the former does not do reactive programming, many unnecessary libraries will be introduced, and it may become overspec.
    The latter has a sense of black magic because of the modification of IL, but since it is an old library with many users, I don't feel like avoiding it.

    I'd like you to read this article carefully so that you can read it and decide which one to choose.

    Qiita: INotifyPropertyChanged Property Implementation Summary C # 3 to C # 7, Fody also

  • Answer # 3

    For example,
    Create a Model class named AccelerationSensorsService
    Publish X, Y, Z properties with change notifications in that class
    Is it OK if you publish the instance in ViewModel?

  • Answer # 4

    1 Use #region
    https://msdn.microsoft.com/en-us/library/windows/apps/9a1ybwek(v=vs.120)

    2 Use the MVVM library because it has convenient functions.
    https://qiita.com/kiichi54321/items/89f5a6d265710b51aa0d
    Combine code snippets.

    public string property {get {return _property;} set {Set (ref _property, value);}}
    private string _property = default (string);


    This amount of description is enough

    3 If you want to harden around the sensor, create a VM for it.
    Alternatively, you can place the VM inside the VM.

    public class Main VM
    {
      public sensor VM sensor VM {get;set;} = new sensor VM ();
    }

    Is it cool to create a service class and do DI?

    4 Make the property a class.

    public class property<T> ;: INotifyPropertyChanged
    {
      private T _value = defult (T);
      public T Value {
    Classic INotifyPropertyChanged processing
      }
    }


    How to use

    public class Main VM
    {
      public property<int>property name {get;} = new property<int>();
    }


    Well, it's the same as a zero-function reactive property.