Fred
Fred

Reputation: 5808

Creating ObservableCollection from class

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

Answers (3)

Mayank
Mayank

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

svinja
svinja

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

Daniel Hilgarth
Daniel Hilgarth

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

Related Questions