Home > Enterprise >  DataContext of usercontrol in WPF
DataContext of usercontrol in WPF

Time:08-27

I'm new to WPF and I'm trying to start a little project with a maximum of good practice. I'm using MVVM and dependency injection. I have a concern which seems to be easy to understand but i can't find an answer (at this step, DataContext is not very clear for me). The UserControlView of type UserControl contains just a button for testing.

This is the app class :

public App()
    {
        IServiceCollection services = new ServiceCollection();
        services.AddSingleton<MainWindow>();
        services.AddSingleton<UserControlViewModel>();
        services.AddSingleton<UserControlView>();

        _serviceProvider = services.BuildServiceProvider();
    }

The user control is included in the Main windows like that :

<Grid>
    <views:UserControlView/>
</Grid>

Now, in the OnStartup overrided method :

protected override void OnStartup(StartupEventArgs e)
    {
        MainWindow = _serviceProvider.GetRequiredService<MainWindow>();
        MainWindow.DataContext = _serviceProvider.GetRequiredService<PaymentMeansViewModel>();
        MainWindow.Show();
    }

Like that it works, my button is correctly binded to the command.

But what is strange for me is that I have to set the 'UserControlViewModel' as the DataContext of the Main Window. Isn'it possible to bind it to the 'UserControlView', something like :

 protected override void OnStartup(StartupEventArgs e)
    {
        MainWindow = _serviceProvider.GetRequiredService<MainWindow>();

        UserControlView testUC = _serviceProvider.GetRequiredService<UserControlView>();
        testUC.DataContext = _serviceProvider.GetRequiredService<UserControlViewModel>();
        MainWindow.Show();
    }

Thanks for help.

CodePudding user response:

Finally I did it. I think (I hope I'm right) that I understood.

First of all, let's begin with the basic. A view must have a viewmodel to bind the properties. A usercontrol is a kind of view "encapsulated" in a view. Therefore a usercontrol must have its own viewmodel and the view must have its own viewmodel.

The datacontext of the MainWindow is set in the app onstartup method :

MainWindow = new MainWindow()
{
    DataContext = new MainWindowViewModel()
};

MainWindow must implement INotifyPropertyChanged. All view models must implement this interface. We can create a base class which will be derived in the view models :

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged(string? propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

The DataContext of the usercontrol must be explicit in the xaml of the MainWindow:

<Grid>
    <views:UserControlView DataContext="{Binding CurrentViewModel}"/>
</Grid>

"CurrentViewModel" is a DataContext, then it's a ViewModel, and as it is binded, it must be a property of the MainViewModel.

 public class MainWindowViewModel : ViewModelBase
{
    public ViewModelBase CurrentViewModel { get; }
    public MainWindowViewModel()
    {
        CurrentViewModel=new UserControlViewModel();
    }
}

Hope it can help.

  • Related