1

I have two views in window one of them load data asynchronously. How can i Notify second view that data is loaded and it need to update data in label? Make singleton with callback?

MainWindow.xaml

    <Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <views:FirstView Grid.Column="0"></views:FirstView>
        <views:SecondView Grid.Column="1"></views:SecondView>
    </Grid>
</Grid>

FirstView.xaml

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Button Grid.Column="0" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Command="{Binding LoadData}"/>
    <ListView ItemsSource="{Binding Items}" Grid.Column="1">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Label Content="{Binding Name}" Grid.Column="0"></Label>
                    <Label Content="{Binding Hours}" Grid.Column="1"></Label>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

FirstViewModel:

 public class FirstViewModel : ViewModelBase
{
    /// <summary>
    /// Initializes a new instance of the FirstViewModel class.
    /// </summary>
    public ObservableCollection<ItemStruct> Items { get; set; }
    public ICommand LoadData { get; set; }
    public FirstViewModel()
    {
        LoadData = new RelayCommand(() => LongLoadData());
        Items = new ObservableCollection<ItemStruct>();
        Items.Add(new ItemStruct { Name="First",Hours="Loading"});
        Items.Add(new ItemStruct { Name = "Second",Hours="Loading" });
    }
    public void LongLoadData()
    {
        Action Load = new Action(AsyncLoad);
        IAsyncResult result = Load.BeginInvoke(null, null);
    }

    private void AsyncLoad()
    {

        foreach (ItemStruct item in Items)
        {
            Random rnd = new Random();
            System.Threading.Thread.Sleep(3000);
            item.Hours = rnd.Next(1, 100).ToString();
        }
    }
}

SecondView.xaml:

 <Grid>
    <ListView ItemsSource="{Binding Items}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Label Content="{Binding Name}" Grid.Column="0"></Label>
                    <Label Content="{Binding Hours}" Grid.Column="1"></Label>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

SecondViewModel:

    public class SecondViewModel : ViewModelBase
{
    public ObservableCollection<ItemStruct> Items { get; set; }
    public SecondViewModel()
    {
        Items = new ObservableCollection<ItemStruct>();
        Items.Add(new ItemStruct { Name="First",Hours="Loading"});
        Items.Add(new ItemStruct { Name = "Second",Hours="Loading" });
    }
}
3
  • I think you should not separate the MainWindow.xaml into two subviews. So you can use one view model. Anyway, I suggest you use dependency injection to initiate the one view model (which contains all properties for the single view). Also, I rahter use the TPL for long running task and in its continuation you can notify the view model about the change. Commented Jul 23, 2015 at 12:08
  • Does ItemStruct implement INotifyPropertyChanged? Commented Jul 23, 2015 at 12:18
  • Yes ItemStruct Implement's "RaisePropertyChanged" Commented Jul 23, 2015 at 12:20

1 Answer 1

2

You can use MvvmLight Messenger for communication between VM's. Inject it into child ViewModels.

public FirstVieModel(IMessenger messenger)
{
   this.messenger = messenger;
}

When data loaded invoke messenger(send) with proper message.

this.messenger.Send<SomethingLoadedMessage>(new SomethingLoadedMessage(..));

In reciever ViewModel handling is also quite simple:

this.messenger.Register<SomethingLoadedMessage>(this, OnSomethingLoaded);

Using messenger generally is a good practice when it comes to buildng loosly coupled multi-conpoment WPF apps.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 messaging is the way to go. All the good MVVM frameworks provide a way to do messaging (or pub/sub) between components. MvvmLight's Messenger, CaliburnMicro's EventAggregator, Catel's MessageMediator, ReactiveUI's MessageBus. Having said that, log.paulbetts.org/messagebus-and-why-you-shouldnt-use-it and use a message system as a last resort, and only between viewmodels, never the view.

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.