Reputation: 95
Im having some trouble in my windows phone project.
The items I create programatically and add to my view doesn´t seem to get updated when using observable collection. The viewmodel and datacontext is correct but nothing happens in the view.
View:
async void OnLoaded(object sender, RoutedEventArgs e)
{
if (InspectionMainMenu.Children.Count() > 0)
return;
await InspectionMainPageViewModel.Instance.LoadData();
this.DataContext = InspectionMainPageViewModel.Instance;
int nrOfGridRows = InspectionMainPageViewModel.Instance.MenuItems.Count / 2;
//check if there is need to add another row
if (InspectionMainPageViewModel.Instance.MenuItems.Count % 2 > 0)
nrOfGridRows++;
Grid grid1 = new Grid();
grid1.Name = "grid1";
grid1.Margin = new Thickness { Top = 0, Left = 0, Bottom = 12, Right = 0 };
InspectionMainMenu.Children.Add(grid1); // Note: parentControl is whatever control you are added this to
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions.Add(new ColumnDefinition ());
//grid1.DataContext = InspectionMainPageViewModel.Instance.MenuItems;
//Binding myBinding = new Binding("MenuItems");
//myBinding.Source = InspectionMainPageViewModel.Instance;
//grid1.SetBinding(Grid.DataContextProperty, myBinding);
//Add the dynamic rows
for (int i = 0; i < nrOfGridRows; i++)
{
grid1.RowDefinitions.Add(new RowDefinition());
}
int currentRow = 0;
int currentColumn = 0;
int currentItem = 0;
foreach(InspectionMenuItem item in InspectionMainPageViewModel.Instance.MenuItems)
{
InspectionCategory menuBox = new InspectionCategory();
menuBox.Title = item.Header;
menuBox.BgColor = App.Current.Resources["Blue"].ToString();
menuBox.SetValue(Grid.RowProperty, currentRow);
menuBox.SetValue(Grid.ColumnProperty, currentColumn);
menuBox.Margin = new Thickness { Top = 0, Left = 6, Bottom = 6, Right = 6 };
menuBox.IconType = "/images/appicons/"+ item.IconName +"";
menuBox.Tap += test2_Tap;
grid1.Children.Add(menuBox);
if (currentItem % 2 > 0)
currentRow++;
if (currentItem % 2 > 0)
currentColumn = 0;
else
currentColumn = 1;
currentItem++;
}
}
Model:
public class InspectionMenuItem : ViewModelBase
{
string _header;
string _bgColor;
string _iconName;
bool _isRead;
public int id { get; set; }
/// <summary>
/// Header.
/// </summary>
public string Header
{
get
{
return _header;
}
set
{
_header = value;
OnPropertyChanged("Header");
}
}
/// <summary>
/// BgColor.
/// </summary>
public string BgColor
{
get
{
return _bgColor;
}
set
{
_bgColor = value;
OnPropertyChanged("BgColor");
}
}
/// <summary>
/// IconName
/// </summary>
public string IconName
{
get
{
return _iconName;
}
set
{
_iconName = value;
OnPropertyChanged("IconName");
}
}
}
ViewModel:
public class InspectionMainPageViewModel : ViewModelBase, INotifyPropertyChanged
{
private static InspectionMainPageViewModel instance;
private TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
private ObservableCollection<InspectionMenuItem> menuItems;
private ObservableCollection<ProtocolItem> protocolItems;
private string chassisNumber;
/// <summary>
/// Initializes a new instance of the <see cref="MainViewModel"/> class.
/// </summary>
public InspectionMainPageViewModel()
{
this.menuItems = new ObservableCollection<InspectionMenuItem>();
this.protocolItems = new ObservableCollection<ProtocolItem>();
}
/// <summary>
/// Gets the instance.
/// </summary>
public static InspectionMainPageViewModel Instance
{
get
{
if (instance == null)
{
instance = new InspectionMainPageViewModel();
}
return instance;
}
}
public ObservableCollection<InspectionMenuItem> MenuItems
{
get
{
return this.menuItems;
}
}
public ObservableCollection<ProtocolItem> ProtocolItems
{
get
{
return this.protocolItems;
}
}
public string ChassisNumber
{
get
{
return this.chassisNumber;
}
}
/// <summary>
/// Gets or sets a value indicating whether this instance is data loaded.
/// </summary>
public bool IsDataLoaded
{
get;
set;
}
public async Task LoadData()
{
if (this.IsDataLoaded)
{
return;
}
GetMenuItems();
GetProtocolItems();
SetDummyData();
// this.news = await CRMService.GetNews();
this.IsDataLoaded = true;
}
private void SetDummyData()
{
this.chassisNumber = "JN1HS36P8LW107899";
}
public void GetMenuItems()
{
this.menuItems.Add(new InspectionMenuItem { Header = "Kund", IconName = "user_128.png", BgColor = "Blue" });
this.menuItems.Add(new InspectionMenuItem { Header = "Fordon", IconName = "car_128.png", BgColor = "Blue" });
this.menuItems.Add(new InspectionMenuItem { Header = "Identifiering", IconName = "check_128.png", BgColor = "Blue" });
this.menuItems.Add(new InspectionMenuItem { Header = "Anmärkning", IconName = "user_128.png", BgColor = "Blue" });
this.menuItems.Add(new InspectionMenuItem { Header = "Test", IconName = "user_128.png", BgColor = "Blue" });
}
public void GetProtocolItems()
{
this.protocolItems.Add(new ProtocolItem { Header = "Spindelled", Summary = "Fastsättning bristfällig", ProtocolImageUri = "user_128.png" , State="Tidigare anmärkningar"});
this.protocolItems.Add(new ProtocolItem { Header = "Färdbroms bromsskiva", Summary = "Risk för bromsbortfall", ProtocolImageUri = "user_128.png", State = "Tidigare anmärkningar" });
this.protocolItems.Add(new ProtocolItem { Header = "Infästning bromssystem", Summary = "Sprickor", ProtocolImageUri = "user_128.png", State = "Tidigare anmärkningar" });
this.protocolItems.Add(new ProtocolItem { Header = "Motor", Summary = "Topplocket sprucket", ProtocolImageUri = "user_128.png", State = "Anmärkningar" });
this.protocolItems.Add(new ProtocolItem { Header = "Lysen", Summary = "Felvinklat halvljus", ProtocolImageUri = "user_128.png", State = "Anmärkningar" });
this.protocolItems.Add(new ProtocolItem { Header = "Kylare", Summary = "Läckande kylare", ProtocolImageUri = "user_128.png", State = "Anmärkningar" });
}
}
Any suggestions on how to solve this?
Best regards, Jonas
Upvotes: 0
Views: 2317
Reputation: 11
As you say "But if I update the viewmodel from another view, hit back on my phone nothing happens."
Just confirm if you are creating new object of ViewModel in other view or not. If yes then you might be updating observable collection of this newly created instance.
Try making your viewModel singleton.
Upvotes: 0
Reputation: 2617
If you want this functionality, you should Imaplement INotifyPropertyChanged
in ViewModel also
It worked in MY code
Upvotes: 0
Reputation: 3568
You have an Event called OnCollectionChanged try with that:
http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx
You can watch when the an element is added to a collection or deleted, cleared...
obsList.CollectionChanged += (sender, eventArgs) =>
{
switch (eventArgs.Action)
{
case NotifyCollectionChangedAction.Remove:
foreach (var oldItem in eventArgs.OldItems)
{
}
break;
case NotifyCollectionChangedAction.Add:
break;
}
};
when that happen, draw again your view.
Upvotes: 0
Reputation: 12465
The ObservableCollection
should automatically update if you add or remove items from the collection.
If you modify the contents of the collection itself though, you would need to fire some events to notify the view that the element has changed. That is, the Model should implement INotifyPropertyChanged
.
Upvotes: 1