Search code examples
performancemvvmuwpparent-childobserver-pattern

Pass data child->parent only when parent presses button


I have a UWP app using MVVM Toolkit. I have a parent ViewModel and a child UserControl. Everyone says I should pass data from child to parent using Observer pattern. Which is good. MVVM Toolkit provides some classes and methods Send/Receive.

Question

How do I pass data from child user control to parent? The child has 10 text boxes and the parent needs that data after clicking a button 'Create File'. I cannot use Observer Send method after each key press in a text box.

MainPage.xaml

<Grid>...
    <uc:MetadataUserControl>
    </uc:MetadataUserControl>

    <Button Content="Create final"></Button>
</Grid>

MainPageViewModel.cs

private MainPageModel _mainPageModel = null; // Business layer model
public MainPageModel MainPageModel
{
    get { return _mainPageModel; }
    set { SetProperty(ref _mainPageModel, value); }
}

void Receive() { .. } // Receive data from user controls

MainPageModel.cs

    public MetadataModel {get; set;}

MetadataViewModel.cs

private MetadataModel _metadataModel = null; // Business layer model
public MetadataModel MetadataModel
{
    get { return _metadataModel; }
    set { SetProperty(ref _metadataModel, value); }
}

void Send() {} // Notify parents subscribed to this user control

MetadataUserControl.xaml

<Grid>
    <!-- First textbox -->
    <TextBlock Text="First textbox"></TextBlock>
    <TextBox Text="{x:Bind Path=ViewModel.MetadataModel.FirstText}"></TextBox>

    <!-- Second textbox -->
    <TextBlock Text="Second textbox"></TextBlock>
    <TextBox Text="{x:Bind Path=ViewModel.MetadataModel.SecondText}"></TextBox>
    ...
</Grid>

SecondMainPage.xaml

<Grid>...
    <uc:MetadataUserControl>
    </uc:MetadataUserControl>

    <Button Content="Create final"></Button>
</Grid>

Solution

  • Managed to do it using Messenger's request feature. When the parent sends an event, the children replies with the object required.

    MainViewModel.cs

    private void CreateFile()
    {
        // Request data from children user controls
        var metadataRequested = WeakReferenceMessenger.Default.Send<MetadataRequestMessage>();
        
    }
    

    MetadataViewModel.cs constructor

    WeakReferenceMessenger.Default.Register<MetadataViewModel, MetadataRequestMessage>(this, (r, m) =>
    {
        m.Reply(r.MetadataModel);
    });
    
    .. 
    public class MetadataRequestMessage : RequestMessage<MetadataModel>
    {
    }