views:

84

answers:

3

MVVM pattern is implemented in my Silverlight4 application.

Originally, I worked with ObservableCollection of objects in my ViewModel:

public class SquadViewModel : ViewModelBase<ISquadModel>
{
    public SquadViewModel(...) : base(...)
    {
        SquadPlayers = new ObservableCollection<SquadPlayerViewModel>();
        ...
        _model.DataReceivedEvent += _model_DataReceivedEvent;
        _model.RequestData(...);
    }

    private void _model_DataReceivedEvent(ObservableCollection<TeamPlayerData> allReadyPlayers, ...)
    {
        foreach (TeamPlayerData tpd in allReadyPlayers)
        {
            SquadPlayerViewModel sp = new SquadPlayerViewModel(...);
            SquadPlayers.Add(sp);
        }
    }
    ...
}

Here is a peacie of XAML code for grid displaying:

xmlns:DataControls="clr-namespace:System.Windows.Controls;
                    assembly=System.Windows.Controls.Data"
...
<DataControls:DataGrid ItemsSource="{Binding SquadPlayers}">
    ...</DataControls:DataGrid>

and my ViewModel is bound to DataContext property of the view.

This collection (SquadPlayers) is not changed after its creation so I would like to change its type to

List<SquadPlayerViewModel>

. When I did that, I also added

RaisePropertyChanged("SquadPlayers")

in the end of '_model_DataReceivedEvent' method (to notify the grid that list data are changed.

The problem is that on initial displaying grid doesn't show any record... Only when I click on any column header it will do 'sorting' and display all items from the list...

Question1: Why datagrid doesn't contain items initially? Q2: How to make them displayed automatically?

Thanks.

P.S. Here is a declaration of the new List object in my view-model:

        public List<SquadPlayerViewModel> SquadPlayers { get; set; }
+1  A: 

The problem is that whilst the PropertyChanged event informs the binding of a "change" the value hasn't actually changed, the collection object is still the same object. Some controls save themselves some percieved unnecessary work if they believe the value hasn't really changed.

Try creating a new instance of the ObservableCollection and assigning to the property. In that case the currently assigned object will differ from the new one you create when data is available.

AnthonyWJones
Adding a new list to a grid is a good idea, agree... but I don't see how can I bind new list from ViewModel to a grid (that is an object from the View layer). I would appreciate if you could clarify that. Thank you.
Budda
+2  A: 
Mike
Hey, Mike, in my original statement I've mentioned that observable collection is not changed after original initialization. Due to this i was to REPLACE ObservableCollection<> with List<>. Was not I mention that?
Budda
That's why i said "something like". Replace ObservableCollection with List. This was a snippet from some working code that I have that i just changed some of the names to fit your example.The point was mostly to make sure that the List is defined completely as a property. This was a shot in the dark since I don't know how you have the List declared or have a full view of your XAML.
Mike
Mike, thanks for your time. List was declared as a property and I've added that into description. Please let me know if you have any other thoughts
Budda
+2  A: 

Budda,

You can't use List as a binding source, because List not implement INotifyCollectionChanged it is require for WPF/Silverlight to have knowledge for whether the content of collection is change or not. WPF/Sivlerlight than can take further action.

I don't know why you need List<> on your view model, but If for abstraction reason you can use IList<> instead. but make sure you put instance of ObservableCollection<> on it, not the List<>. No matter what Type you used in your ViewModel Binding Only care about runtime type.

so your code should like this:

//Your declaration
public IList<SquadPlayerViewModel> SquadPlayers { get; set; }
//in your implementation for WPF/Silverlight you should do
SquadPlayers = new ObservableCollection<SquadPlayerViewModel>();
//but for other reason (for non WPF binding) you can do
SquadPlayers = new List<SquadPlayerViewModel>();

I usually used this approach to abstract my "Proxied" Domain Model that returned by NHibernate.

Hope that help.

ktutnik
If I correctly understood, if I want to use List<> for binding purpose, the workaround (RaisePropertyChanged("SquadPlayers");) won't help. Right?Thank you.
Budda
Yes and No, Yes if you do assignmen to `SquadPlayers = blah.. blah..` but no for `SquadPlayers.Add(blah..blah)`. Mark that `RaisePropertyChanged("SquadPlayers")` work when the instance of collection `SquadPlayers` is changed to new one but that wasn't enough because collection need to notify weather its items is changed (added or removed).
ktutnik
Got a difference,... The 1st issue I see: I notified that collection changed, but actually collection was the same, only its items were changed. Today I will try to replace collection (but I guess, this will break a binding at all). So I need to notify that collection items are changed... and if I correctly understood - that is not possible for List<>. Am I right?
Budda