My ViewModel Constructor is executed before my property is set. So I am having to put my method ( RefreshData )that I want to execute in the Constructor in the ApplyQueryAttributes method.

Tom Meier 220 Reputation points
2024-06-13T18:18:55.96+00:00

My ViewModel Constructor is executed before my property is set

Id = myPackage.packageId;

. So I am having to put my method ( RefreshData ) that I want to execute in the Constructor in the ApplyQueryAttributes method. Otherwise, My parameter value is blank. Can someone please tell me why I can't call my Method in the Constructor, with the value set. Thanks

public void ApplyQuerySttributes(IDictionary<string,object> query)
{
    Package myPackage=query["MyPackage"] as Package;
    Id = myPackage.packageId;
    RefreshData();
}






.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,197 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,615 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 51,071 Reputation points
    2024-06-13T18:38:09.7966667+00:00

    I'm not sure I follow your concern. In order to use an object it must first be created. That is what the constructor does. A constructor always runs before the caller has access to any of the data to be set. Here's the rough "flow" of object initialization. Given:

    (1) var obj = new SomeClass();
    (2) obj.Property1 = "Value";
    

    And the general flow for line 1. Note I'm leaving out things not relevant to this example.

    1. new is executed and memory is allocated for the object.
    2. All field initializers defined within the type are executed.
    3. If the type derives from a class then the base class's constructor runs (going all the way back to the root of the type hierarchy).
    4. The type's constructor executes.
    5. The newly created object is used as the value of the new expression.
    6. The assignment sets obj to the newly created object.

    Line 1 is complete and then we move to line 2.

    1. Assign the given value to the property of the object.

    Note that if you use object initializer syntax then the compiler simply rewrites your code to the above equivalent.

    Thus the only values accessible within a constructor are the fields that may or may not have been initialized by initializer expressions and the parameters to the constructor. If you need to set a field/property based upon some value outside the type then you would need to pass it as a parameter to the constructor. For example suppose SomeClass needs to know the Id of the object it is working against AND that value won't change for the life of the instance. In that case it would need to be a parameter to the constructor.

    public class SomeClass
    {
       public SomeClass ( int id )  
       {  
          Id = id;
       }
    
       public int Id { get; }
    }
    
    var obj = new SomeClass(1);
    

    Constructors should just set fields/properties of an object. If data is needed to do that then use parameters. Constructors should not call methods that may be virtual, need to do extensive work or will likely fail as that makes it harder to work with the type. In your case if RefreshData is simply updating fields based upon the parameters to the constructor then go ahead and call it within the constructor. However if RefreshData is going to do something like query a database or make an API call then it does not belong in the constructor. Ideally have the caller "refresh" the data when it is ready. In other cases you can defer the refresh until you actually need the data which should be some time after the constructor is run.


1 additional answer

Sort by: Most helpful
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 38,906 Reputation points Microsoft Vendor
    2024-06-14T03:03:32.6133333+00:00

    Hello,

    The reason for this problem is that the ID does not call a method to actively send a notification of the value change so that the View layer can take action.

    Please refer to the description and sample code in the following official documents.

    Viewmodels typically implement the INotifyPropertyChanged interface, which provides the ability for a class to raise the PropertyChanged event whenever one of its properties changes. The data binding mechanism in .NET MAUI attaches a handler to this PropertyChanged event so it can be notified when a property changes and keep the target updated with the new value. In the previous code example, the OnPropertyChanged method handles raising the event while automatically determining the property source name: DateTime. Data binding and MVVM

    class TestViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
     
        private int iD;
    
     
        public int ID
        {
            get => iD;
            set
            {
                if (iD != value)
                {
                    iD = value;
                    OnPropertyChanged(); // reports this property
                }
            }
        }
     
        public TestViewModel()
        {
            Random r = new Random();
            ID = r.Next();
        }
     
     
        public void OnPropertyChanged([CallerMemberName] string name = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
    

    Best Regards,

    Alec Liu.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.