2

The Community.Toolkit.Mvvm library helps to generate properties for fields using special attributes. How can this attribute be used to automate such a property? How to make such an entry?

using CommunityToolkit.Mvvm.ComponentModel;

public partial class InfoViewModel : BaseViewModel
{
    private readonly A.Info _item;

    public ViewModel(A.Info item)
    {
        _item = item;
    }

    public ViewModel()
    {
        _item = new A.DateInfo();
    }
    
    //[ObservableProperty]
    //private string year;
    public string Year
    {
        get => _item.Year;
        set
        {
            _item.Year = value;
            OnPropertyChanged(nameof(Year));
        }
    }
}
values_wh
  • 71
  • 1
  • 6

2 Answers2

1

Make sure the ViewModel is a partial class. The just decorate a private field with the ObservablePropertyAttribute.

using CommunityToolkit.Mvvm.ComponentModel;

public partial class ViewModel
{
    [ObservableProperty]
    private string year;
}

EDIT

From what you've wrote in the comments, here are some ways to deal with it.

Option 1 - make the Item's Year property observable

using CommunityToolkit.Mvvm.ComponentModel;

public partial class MyItem
{
    [ObservableProperty]
    private string year; 
}

public class ViewModel
{
    public MyItem Item { get; }

    public ViewModel(MyItem item)
    {
        Item = item;
    }

    public ViewModel()
    {
        Item = new MyItem();
    }

    private void Save()
    {
        //do something with item here
    }
}

Bind in xaml like this:

<Entry Text="{Binding Item.Year}" />

Option 2 - an extra property on the view model

using CommunityToolkit.Mvvm.ComponentModel;

public class MyItem
{
    public string Year { get; set; }
}

public partial class ViewModel
{
    private readonly MyItem _item;

    [ObservableProperty]
    private string year;    

    public ViewModel(MyItem item)
    {
        _item = item;
    }

    public ViewModel()
    {
        _item = new MyItem();
    }

    private void Save()
    {
        _item.Year = Year; //synchronize the year values
        //do something with item here
    }
}

Bind in xaml like this:

<Entry Text="{Binding Year}" />
Michal Diviš
  • 2,008
  • 12
  • 19
  • Yes, I edited the post. Of course, I have a partial class and a library connected. The problem is that my code has to set a value for _item.Year, and with the help of the solution above, it will generate just for "year" a field that is not bound to _item – values_wh May 30 '22 at 12:23
  • In that case, you should decorate the `Year` property of the `A.Info` class instead. You can then delete the `Year` property on the view model, make the `_item` a public property and bind to the `Item.Year` property in XAML. – Michal Diviš May 30 '22 at 12:25
  • Everything suits me the way it is. However, my task is precisely to use [ObservableProperty] – values_wh May 30 '22 at 12:36
  • I don't think you can use attributes this way. If you want to make a property observable using the [ObservableProperty] attribute, the property itself has to be attributed, not a parent view model. So either you'd have to add the [ObservableProperty] to the `A.Info.Year` property or use the view model's `Year` property and synchronize it with the `A.Info.Year later. – Michal Diviš May 31 '22 at 06:15
  • You're right. As a result, we came to the conclusion that we need to leave everything as it was. Thanks :) – values_wh Jun 01 '22 at 07:12
  • In my view model, I need to perform an async call so I created an `async Task DoSomething()` method but when I try to decorate it with `[ICommand]` attribute, I get "Cannot apply attribute class ICommand because it is abstract" error. Any idea why? – Sam Jun 09 '22 at 17:16
  • @Sam is the view model class abstract? If that's not the case I'd need to see the code. – Michal Diviš Jun 10 '22 at 06:05
  • @MichalDiviš Here's a question I just created for you to see my code: https://stackoverflow.com/questions/72578034/cant-use-icommand-attribute-in-view-model-using-communitytoolkit-mvvm – Sam Jun 10 '22 at 17:39
0

Toolkit contains base class: ObservableObject with SetProperty method. Use this class for your VM. Or BaseViewModel : ObservableObject

class MyViewModel : ObservableObject
{
   private string _value;
   public string Value { get = _value; set => SetProperty(ref _value, value); }
}
Aarnihauta
  • 441
  • 3
  • 10
  • I believe @vikachto was asking about the source generator version, using the `ObservableProperty` attribute, not about this base class. – Michal Diviš May 30 '22 at 12:22