I'm trying to produce an error list much like the one in Visual Studio.
I have a view and the view model. I update the singleton view model and notify that changes have occurred to the property which are the actual messages (errors and warnings). However, the grid remains unchanged - what is wrong?!
I have stepped through, the collection _messages is updated correctly and an initial message is shown correctly but remain in view after the view model update. In other words it should be a matter of making the view update according to a correct view model.
I am aware of the bug in RadPane that causes Panes to loose it's connection to view model and have implemented the standard workaround.
The view model implements INotifyPropertyChanged.
(The NotifySourceUpdated in xaml added in an attempt to remedy, but to no avail)
(Brackets replaced in View due to Stackoverflow restrictions)
Thanks for any input and insight...
Anders, Denmark
View:
[Controls:RadPane x:Class="Rap1D.Rap1D_WPF.Views.ErrorListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:Controls="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Docking" xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView" mc:Ignorable="d"
d:DesignHeight="74" d:DesignWidth="298" Header="{Binding Header}" DataContextChanged="RadPane_DataContextChanged"]
[Grid]
[telerik:RadGridView AutoGenerateColumns="False" x:Name="grid" ItemsSource="{Binding Path=Messages, NotifyOnSourceUpdated=True}" Margin="0,0,0,37"]
[telerik:RadGridView.Columns]
[telerik:GridViewDataColumn Header="Message" DataMemberBinding="{Binding Path=Message, NotifyOnSourceUpdated=True}" /]
[/telerik:RadGridView.Columns]
[/telerik:RadGridView]
[/Grid]
[/Controls:RadPane]
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using Rap1D.ViewModelLayer.Interfaces;
using Rap1D.ViewModelLayer.Interfaces.TreeViewItems;
namespace Rap1D.ViewModelLayer.Implementations
{
public class ErrorListViewModel :ViewModelBase, IErrorListViewModel
{
private readonly List<INotificationMessage> _messages;
public ErrorListViewModel()
{
_messages = new List<INotificationMessage>();
}
public string Header
{
get { return "Error List"; }
}
public IEnumerable<INotificationMessage> Messages
{
get { return _messages; }
}
public void RemoveNotificationsForItem(IProductComponentViewModel productComponentViewModel)
{
var toDelete = (from m in _messages
where m.Item == productComponentViewModel
select m).ToList();
foreach (var notificationMessage in toDelete)
{
_messages.Remove(notificationMessage);
}
OnPropertyChanged("Messages");
}
public void AddNotifications(IProductComponentViewModel productComponentViewModel, IEnumerable<INotificationMessage> list)
{
_messages.AddRange(list);
OnPropertyChanged("Messages");
}
}
}
ErrorManager:
using System.Collections.Generic;
using Rap1D.ViewModelLayer.Interfaces;
using Rap1D.ViewModelLayer.Interfaces.Managers;
using Rap1D.ViewModelLayer.Interfaces.Providers;
using Rap1D.ViewModelLayer.Interfaces.TreeViewItems;
namespace Rap1D.ViewModelLayer.Implementations.Managers
{
public class ErrorManager : IErrorManager
{
private readonly IErrorListViewModelProvider _errorListViewModelProvider;
public ErrorManager(IErrorListViewModelProvider errorListViewModelProvider)
{
_errorListViewModelProvider = errorListViewModelProvider;
}
public void UpdateNotificationsForItem(IProductComponentViewModel productComponentViewModel,
IEnumerable<INotificationMessage> list)
{
var errorListViewModel = _errorListViewModelProvider.GetViewModel();
errorListViewModel.RemoveNotificationsForItem(productComponentViewModel);
errorListViewModel.AddNotifications(pr开发者_StackOverflowoductComponentViewModel, list);
}
}
}
All it took was changing to List to ObservableCollection.
Can someone explain why my initial solution didn't work as expected?
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Practices.Prism;
using Rap1D.ViewModelLayer.Interfaces;
using Rap1D.ViewModelLayer.Interfaces.TreeViewItems;
namespace Rap1D.ViewModelLayer.Implementations
{
public class ErrorListViewModel : ViewModelBase, IErrorListViewModel
{
private readonly ObservableCollection<INotificationMessage> _messages;
public ErrorListViewModel()
{
_messages = new ObservableCollection<INotificationMessage>();
}
public string Header
{
get { return "Error List"; }
}
public void AddNotifications(IProductComponentViewModel productComponentViewModel,
IEnumerable<INotificationMessage> list)
{
_messages.AddRange(list);
OnPropertyChanged("Messages");
}
public IEnumerable<INotificationMessage> Messages
{
get { return _messages; }
}
public void RemoveNotificationsForItem(IProductComponentViewModel productComponentViewModel)
{
var toDelete = (from m in _messages
//where m.Item == productComponentViewModel
select m).ToList();
foreach (var notificationMessage in toDelete)
{
_messages.Remove(notificationMessage);
}
OnPropertyChanged("Messages");
}
}
}
ObservableCollections support PropertyChangeNotification; other collections require RaisePropertyChanged("ObjectName")
.
精彩评论