Search code examples
c#mvvmuwpdatacontext

How to bind command and contexrt from UserControl to MainView UWP MVVM


There is a form in which the label is located, as well as a user control wrapped in a button. I need to change the text in the TextBlock by clicking the button in the user control. I didn't use any MVVM frameworks. Main XAML:

    <Page.DataContext>
    <local:MainViewModel />
</Page.DataContext>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="553*" />
        <ColumnDefinition Width="197*" />
    </Grid.ColumnDefinitions>
    <local:ControlView Grid.Column="1" HorizontalAlignment="Stretch"
                       VerticalAlignment="Stretch" />
    <TextBlock Grid.Column="0" Foreground="Black" FontSize="50" VerticalAlignment="Stretch"
               HorizontalAlignment="Stretch" Text="{Binding UserText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    
</Grid>

User Conrol Xaml:

<Grid>
    <Button Width="300" Height="100" FontSize="50" Command="{Binding}"
            VerticalAlignment="Center" HorizontalAlignment="Center" Content="Print chart" />
</Grid>

Main VM:

 public class MainViewModel : INotifyPropertyChanged
{
    public MainViewModel()
    {
        
        SetText = new RelayCommand(SetUserText);
    }

    public ICommand SetText { get; set; }

    public string UserText { get; set; }

    
    public event PropertyChangedEventHandler PropertyChanged;

    private void SetUserText()
    {
        UserText = "Hello World!";
        RaisePropertyChanged(nameof(UserText ));
    }

    
    protected void RaisePropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }
}

And I create an empty user control VN:

public class ControlViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string property)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }

    // And what should I do here?
}

So how to correctly implement commands from user control to main view, f.e SetText property?


Solution

  • Your main issue is there is the use of the ControlViewModel. UserControls such as ControlView should generally speaking not set their own DataContext to some specialized view model but rather inherit the DataContext from their parent element.

    Assuming you let the control inherit the DataContext, you could add a dependency property to it and bind the command to this one:

    <local:ControlView YourCommand="{Binding SetText}" />
    

    ControlView.xaml:

    <UserControl ... Name="uc">
        <Button Command="{Binding YourCommand, ElementName=uc}" />