user1069516
user1069516

Reputation: 463

execute a function in a viewmodel and real time refresh of the view

I have a small problem with my MVVM application.

I have a function in a viewmodel which modify a collection. This collection is bind to the view to show a datagrid. When an user click on a button, the function modify the collection but it can take few minutes and the view is not refresh.

My question is how can I execute this function to have the view refreshed in real time ?

In another program I have used the dispatcher but it was in the code behind of the view without binding.

Thanks

Edit :

Model :

public class Composants : INotifyPropertyChanged
{
    private string _nom;

    public string Nom
    {
        get { return _nom; }
        set { _nom = value; OnPropertyChanged("Nom"); }
    }

}

ViewModel :

public class PageSynchroViewModel : INotifyPropertyChanged
{
    public void SynchroniserComposants()
    {
        foreach (var comp in _selectedVersion.ListeComposants)
        {
            comp.Nom = "";
        }
}

View (I don't put all the code):

<Page x:Class="Centre_de_synchronisation.Vues.PageSynchro"
  [...]
  xmlns:app="clr-namespace:Centre_de_synchronisation.Classes" mc:Ignorable="d"
  d:DesignHeight="531" d:DesignWidth="778"
Title="PageSynchro" Background="{x:Null}">
<Canvas>
    [...]
    <DataGrid Name="GridComposants" Style="{StaticResource DatagridStyle}"  ItemsSource="{Binding ListeComposants}" AutoGenerateColumns="False" Canvas.Left="12" Canvas.Top="201" Height="285"  Width="754"  >
        <DataGrid.Columns>
            <DataGridTextColumn
       Header="Nom"
       Binding="{Binding Nom}"
       Width="150"
               IsReadOnly="True"/>
            [...]
    </DataGrid>
    <Button Name="BoutonSynchro" Style="{StaticResource MessageBoxButtonStyle}" Content="Synchroniser" Height="27" Width="107" Command="{Binding BoutonSynchro}" CommandParameter="GridComposants" Visibility="{Binding Etat, Converter={StaticResource VisibilityConverter}}"/>
</Canvas>

Upvotes: 0

Views: 899

Answers (1)

ywm
ywm

Reputation: 1127

Try using an ObservableCollection<T> instead of the collection you are using now.

This should cause the View to be updated whenever an Item is added or removed from the collection.

Just remember when interacted with the ObservableCollection to Invoke the Dispatcher otherwise you will get Thread Access Exceptions

Here is the code I did to test this.

XAML

<Window.Resources>
    <loc:MyViewModel x:Key="ViewModel" />
</Window.Resources>
<Canvas DataContext="{StaticResource ViewModel}">
    <DataGrid ItemsSource="{Binding Collection}"
              Width="150"
              Height="200">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Nom"
                                Binding="{Binding Nom}"
                                Width="150"
                                IsReadOnly="True" />
        </DataGrid.Columns>
    </DataGrid>
    <Button Command="{Binding DoStuffCommand}"
            Canvas.Bottom="0"
            Canvas.Right="0">Stuff</Button>
</Canvas>

ViewModel

public class MyViewModel
{
    public ObservableCollection<MyModel> Collection { get; set; }

    public ICommand DoStuffCommand { get; set; }

    public MyViewModel()
    {
        this.Collection = new ObservableCollection<MyModel>();

        for (int i = 0; i < 10; i++)
        {
            Collection.Add(new MyModel { Nom = i.ToString() });
        }

        this.DoStuffCommand = new RelayCommand(DoStuff);
    }

    private void DoStuff()
    {
        foreach (var item in Collection)
        {
            item.Nom = item.Nom + ".";
        }
    }
}

Model

public class MyModel : INotifyPropertyChanged
{
    private string nom;

    public string Nom
    {
        get { return nom; }
        set
        {
            nom = value;
            RaiseChanged("Nom");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaiseChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

It updated the Nom in the view.

Upvotes: 2

Related Questions