Reputation: 5808
I have a WPF app with an event log. I have an EventLog class I populate with saved events from an XML file when the app starts
namespace MyApp.Agent.EventLogging
{
public enum EventType
{
Infomation,
Error
}
public class EventLog
{
public String Image { get; set; }
public DateTime EventDate { get; set; }
public String EventText { get; set; }
}
}
public List<EventLog> GetSavedEvents()
{
string file = XmlUtilities.GetXmlLocation() + "\\Events.xml";
List<EventLog> elog = new List<EventLog>();
try
{
if (File.Exists(file))
{
Serialize<List<EventLog>> ser = new Serialize<List<EventLog>>();
elog = ser.DeserializeDocToObj(file);
}
}
catch
{
throw new InvalidEventLogException(ConfigurationManager.AppSettings.Get("EventLogFileInvalid"));
}
return elog;
}
I then convert this into an observable collection that a listview is bound to
List<EventLog> _evtLog = new List<EventLog>();
ObservableCollection<EventLog> _eventLog = new ObservableCollection<EventLog>();
_evtLog = logger.GetSavedEvents();
_evtLog.ForEach(x => _eventLog.Add(x));
I read that this is how it has to been done (although it seems a long winded way)
As the app is running new events are added to the observable collection. When the app closes I reverse this process to save the events.
While this works fine if there are only a few saved events as the list is getting bigger so the time it takes to do this is getting unrealistic (240K events is taking 7 secs). Ok first question you may ask is why would I want that many events anyway, truth is I don't but it does highlight that I am not doing this the best way?
So my questions are:
Do I really need to populate the observable collection? Can I not make _evtLog
Observable without populating one from the other?
Can I restrict these lists to X events based on the date of the event?
Upvotes: 0
Views: 584
Reputation: 8852
following will create ObservableCollection
var _eventLog = new ObservableCollection<EventLog>(logger.GetSavedEvents());
regarding filtering your results, yes you can do a quick LINQ
select query where you define the restrictions and get the results as a List
which you'll pass to ObservableCollection
some idea's on filtering results
you might need some tweaking depending on your needs
var _eventLog = new ObservableCollection<EventLog>(logger.GetSavedEvents().where(event => event.date == some date).ToList());
Upvotes: 2
Reputation: 5576
Is this the actual code that generates the ObservableCollection? Generating an OC from a 240k element list should NOT take 7 seconds, it should be nearly instantaneous.
Are you sure you are not adding events to a collection that is already bound to a listview, causing the listview to be updated for each item?
Try using this instead of ObservableCollection:
class MyObservableCollection<T> : ObservableCollection<T>
{
private bool _notifyCollectionChanged = true;
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (_notifyCollectionChanged)
base.OnCollectionChanged(e);
}
public void AddRange(IEnumerable<T> collection)
{
_notifyCollectionChanged = false;
foreach (T element in collection)
Add(element);
_notifyCollectionChanged = true;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
And add the List to the ObservableCollection using oc.AddRange(list).
If this doesn't help, then your GetSavedEvents function is probably what is running for 7 seconds, and it has nothing to do with the ObservableCollection.
Upvotes: 0
Reputation: 174329
You could easily change GetSavedEvents
to serialize and deserialize an ObservableCollection<EventLog>
instead of a List<EventLog>
.
Having said that, the code to convert the list to an observable collection looks strange. Why aren't you just using the appropriate constructor?
_eventLog = new ObservableCollection<EventLog>(logger.GetSavedEvents());
The problem with using Add
is that for each item being added you raise an event.
Upvotes: 2