1

I am trying to write an MVVM and WinUI3 based app. I have a ViewModel property, SelectedFolder, which is observable (using MVVM Toolkit). This is of type Folder which is a plain old class. Something like this:

public class ViewModel: ObservableRecipient {
    private Folder selectedFolder;
    public FolderModel SelectedFolder
    {
        get => selectedFolder;
        set => SetProperty(ref selectedFolder, value, true);
    }
}
public class FolderModel {
    public string Name { get; set; }
}

Now in my XAML, I want to bind on ViewModel.SelectedFolder, and react to changes on it, but I want to show ViewModel.SelectedFolder.Name. So I am looking for something like this (which doesn't exist):

<TextBlock Text="{Binding ViewModel.SelectedFolder,Property=Name" />

How can I achive that? Things I thought about:

  • Just make everything observable. This worked, but I am trying to avoid this, in order to decouple my model and my viewmodel. The reason is that my real model is a lot more complicated than this example, and I am trying to keep it close to what make sense for my "business logic", and to make my viewmodel cater to my view's needs.
  • Make another "folder" class for my ViewModel's needs which has observable properties. I don't want to do this because it would duplicate a lot of code.
  • Add an observable string property to my ViewModel: "SelectedFolderName".
  • Abuse converters and write a GetNamePropertyConverter, which seems really silly.
3
  • Making a model observable whose changes you want to be observable seems like the most straightforward design choice here. You wouldn't need to make every property observable. Commented Sep 30, 2021 at 17:40
  • Yes, but the properties of Folder aren't going to change, it's basically immutable. I want to swap out the whole object instead. Commented Sep 30, 2021 at 18:03
  • Because your ViewModel is observable, when SelectedFolder changes, the new Name property value will be shown in the UI if you bind to it as {Binding ViewModel.SelectedFolder.Name}. You don't need to do anything else if you only want the data-bound value of Name to change when SelectedFolder is set to a new value. Commented Sep 30, 2021 at 18:05

1 Answer 1

1

Binding to the Name property of the model like this should work since you are setting the SelectedFolder and raise the PropertyChanged event for it:

<TextBlock Text="{Binding ViewModel.SelectedFolder.Name} " />

In general, you should not bind directly to model objects that contain "business logic". Instead you should wrap your model property in the view model and bind to the wrapper properties:

public class ViewModel : ObservableRecipient
{
    private Folder selectedFolder;
    public FolderModel SelectedFolder
    {
        get => selectedFolder;
        set
        {
            SetProperty(ref selectedFolder, value, true);
            OnPropertyChanged(nameof(FolderName));
        }
    }

    public string FolderName => selectedFolder?.Name;
}

XAML:

<TextBlock Text="{Binding FolderName}" />
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, you are absolutely right. I created a new project and it works. I think I might have been hitting some bug in WinUI3 1.0 Preview. I've also had crashes related to bindings (github.com/microsoft/microsoft-ui-xaml/issues/3680). Of course it's also possible that I just had a stupid typo somewhere...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.