I am trying to improve performance by limiting my objects in memory by using a cache.
This creates problem with my ObservableCollection. Well, i think the code speaks for itself. I have "transformed" my ObservableCollection-derivative to this:
public class TrackCollection : INotifyPropertyChanged, IEnumerable {
private readonly List<Guid> _guids = new List<Guid>();
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public void Add(Track track) {
_guids.Add(track.Id);
}
public void Add(Guid trackId) {
_guids.Add(trackId);
}
public IEnumerator GetEnumerator() {
var tracks = new List<Track>(_guids.Count);
foreach(Guid id in _guids)
tracks.Add(MediaCache.Instance.GetTrack(id));
return tracks.GetEnumerator();
}
}
When i call the Add-methods i would like to call my NotifyPropertyChanged on the class it self.
I have a feeling that this is the wrong approach to this kind of problem, it feels like a workaround.
Anyways, is this the correct solution, and if so, how should i proceed?
The cache method looks like this:
private readonly List<Track> _tracks = new List<Track>();
public Track GetTrack(Guid id) {
foreach (var track in _tracks.Where(track => track.Id == id))
return track;
_tracks.Add(Database.Database.Instance.GetTrack(id));
return _tracks[_tracks.Count - 1];
}
If you want your collection to be observable by the binding system, you need to implement INotifyCollectionChanged. This will allow you to notify interested clients about changes in your collection.
On a side note, to notify listeners about a change in the whole class, you can notify about a change to a property with null passed for the name. This will cause all bindings to reevaluate the source.
I looked through the code a bit further and I'm confused about your intention. Every enumeration returns a brand new collection, which doesn't mesh well with the notion of an observable collection. The clients of an observable collection expect the individual instances of their items to stay consistent, so they only need to respond to restructuring, rather than refreshing the whole list. Could your clarify what you're trying to accomplish?
Instead of trying to handle your caching in the collection class, perhaps you can create a 'reference' class TrackReference and use a standard ObservableCollection. The class would look something like:
public class TrackReference
{
private Guid _id;
public Track Track
{
get { return MediaCache.Instance.GetTrack(id); }
}
public TrackReference(Track track)
{
_id = track.Id;
}
public TrackReference(Guid trackId)
{
_id = trackId;
}
}
Now you have a lightweight handle you can pass around (and observe in a collection) that gives you access to the full Track data when you're ready for it. This is also a good place to add any lightweight meta-data (track name, perhaps?) for your UI classes to Bind.
Related
Using RoutedEvents, you can do things such as have a single control which hosts thousands of child controls, but rather than subscribe to MouseDown on each child, you set a handler on the root control and inspect the 'sender' property to find which child was actually clicked on.
I'm wondering if there's any such thing for INPC objects, or if not, can one be created.
For instance, if you have a collection which contains thousands of objects which all implement INPC, currently you have to subscribe to each and every one individually. I'm wondering if there's a way around that.
The only thing I can think of is in the setter property for these properties you're interested in, in addition to raising the standard INPC notification, call a delegate in the containing collection and have the collection raise the appropriate notification. That way the consumer would just have to subscribe to a single handler on the collection for any of its children.
My hesitation here is if you're going to do that, why not just make that collection subscribe to the children itself, then re-raise the notification from the collection? My thought however is that calling a delegate directly from the specific setters you're interested in avoids string comparison in the PropertyChanged handler that would delegate such notifications.
Note: This is pseudo-code typed off the top of my head so it may not compile. It's to illustrate a concept/idea, not to be an example of actual code.
public class ItemCollection : ObservableCollection<Item>
{
public EventHandler ChildItemPropertyChanged(object sender, string propertyName);
internal void RaiseChildItemPropertyChanged(object sender, string propertyName)
{
var childItemPropertyChanged = ChildItemPropertyChanged;
if(childItemPropertyChanged != null)
childItemPropertyChanged(sender, propertyName);
}
}
public class Item : INotifyPropertyChanged
{
public ItemCollection OwningCollection;
public Item(ItemCollection owningCollection)
{
OwningCollection = owningCollection;
}
private string _name;
public string Name
{
get{ return _name; }
set
{
if(_name == value)
return;
_name = value;
PropertyChanged(this, "Name");
OwningCollection.RaiseChildItemPropertyChanged(this, "Name");
}
}
}
Thoughts?
I want to add more functionality to a project I have that makes use a number of classes packaged in the NET Framework. These same classes provide a number of properties which can be quite useful adapting the functionality of my project, however one thing that these classes lack is Events.
If each property had a appropriate event that would fire whenever the value of such property changed, I could then assign a event handler that would act based on those properties value.
I made a sample case bellow to illustrate my goal in the most simpler way I could think off.
Sample case:
The System.Net.Sockets.Socket class (Socket on MSDN Docs) has a property
named Connected that basically returns true if the socket is
connected to a specified end point otherwise returns false.
What I would like to accomplish is simple. I would like to keep this
property under "watch" and when the value of it changes, fire a event.
Doing that to one of my own classes it would be simple although a bit tiresome using the INotifyPropertyChanged interface, simply because always that my code changed the value of the property I would have to fire the event manually. Unfortunately, to best of my knowledge, not even this kind of procedure can be applied to the existing Socket class distributed within NET Framework.
Well, this question is becoming quite extensive, sorry, but I hope it gave an insight to my goal.
Now simply putting it, I want to watch the Connected property of the Socket class and when the value of it changes, fire an event. And if it would be possible to also use such approach to watch variables as well properties, it would be awesome, not just for me, but for everyone who stumbles across this question on SO.
A simple and lightweight approach is preferred of course, but most of all, I want to understand how it can be done, so in the future I can apply it in mass scale to other classes.
I realize I'm asking a lot. Many thanks.
Any questions just ask.
I implemented a basic class that should get you started. I'm sure a fully functional, production-ready, thread-safe class would require a bit more work, plus you need to implement your own strategy for when to poll for value changes.
public class TargettedObserver<T>
{
private static readonly EqualityComparer<T> EqualityComparer = EqualityComparer<T>.Default;
private Func<T> ValueTarget;
private T OldValue;
public event ObservedValueChangedEventHandler<T> ValueChanged;
public TargettedObserver(Func<T> valueTarget)
{
this.ValueTarget = valueTarget;
OldValue = ObtainCurrentValue();
}
public bool CheckValue()
{
T oldValue = OldValue;
T newValue = ObtainCurrentValue();
bool hasValueChanged = CompareValues(oldValue, newValue);
if (hasValueChanged)
{
OldValue = newValue;
NotifyValueChanged(oldValue, newValue);
}
return hasValueChanged;
}
private void NotifyValueChanged(T oldValue, T newValue)
{
var valueChangedEvent = ValueChanged;
if (valueChangedEvent != null)
valueChangedEvent(this, new ObservedValueChangedEventArgs<T>(oldValue, newValue));
}
private static bool CompareValues(T oldValue, T newValue)
{
return !EqualityComparer.Equals(oldValue, newValue);
}
private T ObtainCurrentValue()
{
return ValueTarget();
}
}
And the event handling:
public class ObservedValueChangedEventArgs<T> : EventArgs
{
public T OldValue { get; private set; }
public T NewValue { get; private set; }
public ObservedValueChangedEventArgs(T oldValue, T newValue)
{
this.OldValue = oldValue;
this.NewValue = newValue;
}
}
public delegate void ObservedValueChangedEventHandler<T>(TargettedObserver<T> observer, ObservedValueChangedEventArgs<T> eventArgs);
Usage looks something like this:
public class TestClass
{
private Socket MySocket;
private static TargettedObserver<bool> SocketConnectedObserver;
public void Main()
{
MySocket = new Socket();
SocketConnectedObserver = new TargettedObserver<bool>(() => MySocket.Connected);
SocketConnectedObserver.ValueChanged += ReportSocketConnectedStateChanged;
PerformSocketConnection();
MainThread.Invoke(PollSocketValue);
}
private void PollSocketValue()
{
SocketConnectedObserver.CheckValue();
MainThread.Invoke(PollSocketValue);
}
private void ReportSocketConnectedStateChanged(TargettedObserver<bool> observer, ObservedValueChangedEventArgs<bool> eventArgs)
{
Console.WriteLine("Socket connection state changed! OldValue: " + eventArgs.OldValue + ", NewValue: " + eventArgs.NewValue);
}
}
Notice the constructor takes a simple lambda expression that can evaluate the value you're wanting to observe.
Also note that MainThread.Invoke is just a pseudocode to show it polling for a change on every main thread loop. I'm sure there are nicer strategies (background thread with a timer interval) for example that could be implemented in a nice, reusable way. Still more work to be done in terms of deregistering the observer. Could probably make some nice factory methods or lambda delegates so you don't need to keep the TargettedObserver instance floating around and reduce the amount of wiring/manual code. But at least this should be a start.
What your looking for is an implementation of the Observer Pattern. Something like this Observable<T> implementation might work.
See also the IObserver<T> Interface in .NET 4:
The IObserver<T> and IObservable<T> interfaces provide a generalized
mechanism for push-based notification. The IObservable<T> interface represents the class that
sends notifications (the provider); the IObserver<T> interface
represents the class that receives them (the observer). T represents
the class that provides the notification information.
I've started to learn WPF\MVVM approach and get bit confused.
I've:
class ModelAAA {
public List<Foo> Foos{get; protected set;}
//..
public void Boo()
{
//Some complex logic updating Foos
}
}
class ViewModelAAA{
private ModelAAA _modelAAA
public ObservableCollection<Foo> Foos{get; protected set;}
public void ViewModelAAA(ModelAAA modelAAA)
{
this._modelAAA = modelAAA;
this.Foos = new ObservableCollection(modelAAA.Foos)
}
public void Boo()
{
this._modelAAA.Boo();
//What should I do here?
}
}
So if I use Boo method of view model, what is proper view to update collection in ViewModel. I've got few ideas, but they all seems to by ugly. Should I manauly recreate\change viewModel Foos each time? As I understad ObservableCollection is not wrapper like object.
P.S. I'm want to make it whitout using ObservableCollection in model
Your Model does not need to use ObservableCollection, but has to notify your ViewModel that something changed in the Collection.
this creates a copy of your List, which is indeed observable, but is not changed at all after that:
this.Foos = new ObservableCollection(modelAAA.Foos);
I would not recommend to create a new ObservableCollection, each time the Model-Collection changed. Instead implement the INotifyCollectionChanged in your Model-Collection and handle the events in your Viewmodel properly.
No, you do not need manually change it, as this is ObservableCollection, but you are changing original collection and not observable one.
To notify listeners of your Observable you need to act on Observable itself.
Example:
public void Boo()
{
this.Foos.Boo();
}
So I've got these classes that expose a collection of child objects.
I don't want other classes adding or removing objects from collections because I need to wire into events in the child objects, so as they get added or removed I want to be able to do additional processing. But I really love the ease of manipulating generics internally.
Did I mention this is a WPF app so I need INotifySupport?
The best I can come up with is something like this.
public class foo : INotifyPropertyChanged
{
protected List<ChildFoo> _Children = new List<ChildFoo>();
public foo()
{
}
public void AddChild(ChildFoo newChild)
{
DoAttachLogic(newChild);
_Children.Add(newChild);
NotifyPropertyChange("Children");
}
public void RemoveChild(ChildFoo oldChild)
{
DoRemoveLogic(oldChild);
_Children.Remove(oldChild);
NotifyPropertyChange("Children");
}
public ChildFoo[] Children
{
get
{
return _Children.ToArray();
}
}
}
Are there serious flaws with this design that I'm not seeing?
Every time the Children property is accessed we get the overhead of converting list to an array.
Any advice on this would be great.
This is what I do for normal code:
Public Readonly Property Childern As ObjectModel.ReadOnlyCollection(Of Child)
Get
Return New ObjectModel.ReadOnlyCollection(Of Child)(_ChildernList)
End Get
End Property
For WPF code I would just expose a subclass of ObservableCollection.
You should use ObservableCollection as field in your class, you then have full access to modify collection. Then expose this as ReadonlyObservableCollection via property.
And if you dont change collection itself (eg. nochildren = new ObservableCollection(), you should make field readonly), then you dont need any kind of notifyPropertyChanged on this property, because it doesnt change and collection itself handles those events for its children.
public class Child
{
public int Value { get; set; }
}
class MyClassWithReadonlyCollection
{
private readonly ObservableCollection<Child> _children = new ObservableCollection<Child>();
public MyClassWithReadonlyCollection()
{
_children.Add(new Child());
}
//No need to NotifyPropertyChange, because property doesnt change and collection handles this internaly
public ReadOnlyObservableCollection<Child> Children { get { return new ReadOnlyObservableCollection<Child>(_children); } }
}
I changed the "add child" and "remove child" to protected since you are saying you don't want other classes modifying your collection. I changed your List to ObservableCollection so you can recieve collection changed notifications. Since you are using an IList there is no need to call ToArray(), just access directly.
try this:
public class foo : INotifyPropertyChanged
{
protected ObservableCollection<ChildFoo> _Children = new ObservableCollection<ChildFoo>();
public foo() { }
protected void AddChild(ChildFoo oldChild)
{
DoAttachLogic(newChild);
_Children.Add(newChild);
NotifyPropertyChange("Children");
}
protected void RemoveChild(ChildFoo oldChild)
{
DoRemoveLogic(oldChild);
_Children.Remove(oldChild);
NotifyPropertyChange("Children");
}
public ChildFoo this[int n]
{
get
{
return _Children[n];
}
}
}
You could subclass BindingList and set AllowNew/AllowRemove to false. In your Child Add/Remove methods, you can set it to true, make the changes, then set it back to false. (Of course, you need to hide set access to AllowNew/AllowRemove from outside callers as well).
Another option - subclass Observable collection and override the InsertItem, RemoveItem, etc methods to behave as AddChild/RemoveChild would behave. Then callers can still access it in familiar ways, but not bypass your custom logic.
Subclassing an existing collection class is probably going to be easier (for you and the consumer) than wrapping a collection in another class.
For a newsroom system I have a class that contains a single news story. Inside this class is a private variable holding a generic List of image classes. The idea being a single story can contain multiple images.
The question is should I make the List variable public, so that I can add/remove images by addressing the List directly
public class News
{
private _images List<Images>();
public Images
{
get { return _images; }
set { _images = value }
}
}
or
Should I make the List variable private and then create methods to manipulate it:
public class News
{
private _images List<Images>();
public void AddImage( Image image )
public Image GetImage( int imageId )
public int GetImageCount()
public void DeleteImage( int imageId )
}
My spider sense is telling me to do the later, as it's abstracting things more. But on the flip side its creating more code.
By exposing the List, you expose an implementation detail. It will make it easier in the short run, but you'll have a hard time later if you decide to e.g. change the list to some other container (perhaps you need a Dictionary for lookup or something).
I would encapsulate it as it will make the type easier to maintain and enhance in the future.
I would explose a read-only view of the list as IList or IEnumerable, and methods for adding and removing elements. Like this:
public class News
{
private _images List<Images>();
public IList<Image> Images
{
get {return _images.AsReadOnly(); }
}
public void AddImage(Image image)
{
_images.Add(image);
// Do other stuff...
}
public void DeleteImage(Image image)
{
_images.Remove(image);
// Do other stuff...
}
}
If you expose the list as a property then it will be possible to do the following from outside the class:
News.Images = new List<Images>();
Is that what you want? (and you shouldn't because it breaks allsorts of encapsulation principles)
If not then use an ICollection<T> interface:
class News
{
public ICollection<Image> Images
{
get;
private set;
}
}
or
class News
{
private List<Image> images = new List<Image>();
public ICollection<Image> Images
{
get
{
// You can return an ICollection interface directly from a List
return images;
}
}
}
ICollection<T> has methods such as Add, Remove, Clear, Count.
If you want a read-only container return a ReadOnlyCollection
class News
{
private List<Image> images = new List<Image>();
public ReadOnlyCollection<Image> Images
{
get
{
// This wraps the list in a ReadOnlyCollection object so it doesn't actually copy the contents of the list just a reference to it
return images.AsReadOnly();
}
}
}
It depends on whether you need/(would need) to control adding/getting and deleting images or possibility to change container.
Davy Brion made a post on this last week. He favors exposing an IEnumerable<> property and providing an add & remove method for manipulation.
Most of the time you only want to loop through the collection, so IEnumerable<> will do the trick. Besides, you can switch the actual implementation (List, Set, ...) when needed without any hassle, when switching to another ORM this could prove very valuable.
http://davybrion.com/blog/2009/10/stop-exposing-collections-already/
Expose a read only implementation of the list and expose methods for manipulating the list. I would do it like this:
public class News
{
private IList<Image> _images;
public void News()
{
_images = new List<Image>();
}
public void AddImage(Image image) { ... }
public void RemoveImage(Image image) { ... }
public IEnumberable<Image> Images
{
get { return _images; }
}
}
Note that the Images property can be cast as List but you can return it in a ReadyOnlyCollection wrapper if needed. Count() and ElementAt() extension methods replace your GetImageCount and GetImage methods.
For accessing the elements you could consider using a ReadOnlyCollection or IEnumerable type. However in order to keep encapsulation ensured, you should use insert/remove methods, this way you don't need the set of the property anymore.
Edit: Someone beat me to it during typing this answer ;)
If you expose the List directly, you would have to rely on it's mechanics for all Image-related actions (Add, Delete, Count, ...)
I would still expose a collection of Images (ReadOnlyCollection is usually fine) to make the accessing operations of the list easier for both the developer and the consumer, but all create/update/delete logic should be wrapped inside your class.
I think this is a design consideration that only you can decide. Your second approach is hiding an implementation detail that is you used a List to store images. On the other side, the first solution gives you one advantage. You can use all the List methods including those extensions that are always useful. Using the second solution, you can also implement a ToList() method that would return a new constructed List. Changes to this List wouldn't affect the internal structure of your class. The down side is, if the internal Image List is too big, it could affect performance, as it would always build a new List on ToList() but I wouldn't expect this method be called many times.
Another solution would be to expose a ReadOnlyCollection.
I would just expose the list as an IList:
public class News
{
private List<Image> _images;
public IList<Image> Images
{
get { return _images; }
set { _images = value; }
}
}
If you later want to change the implementation, you can do this without breaking the contract:
public class News
{
public News(SomeCollection<Image> images)
{
_images = images;
Images = new ListView(this);
}
private SomeCollection<Image> _images;
public IList<Image> Images { get; private set; }
private class News.ListView : IList<Image>
{
public ListView(News news)
{
_news = news;
}
private News _news;
// Implement the methods to manipulate _news._images
}
}