I want to override Add(MyType t) for a class derived from ObservableCollection<MyType>. However I cannot override Add. Why?
I therefore added AddIem(MyType t)and use that function instead, which works fine. But I want to prevent someone erroneously using Add so I implemented Add (throwing an exception). But that doesn't hide the Add method of the ObservableCollection. Any idea why and how I could achieve my goal?
Keep your ObservableCollection private, and expose the items with a public ReadOnlyObservableCollection which reflects the items in the private collection.
If you need to expose a specialized AddItem method to other classes, you could make it a member of your viewmodel class, or you could subclass ReadOnlyObservableCollection and put it there. Call it MostlyReadOnlyObservableCollection.
Related
We use controls all the time for example a button and sometimes we may want to add some custom properties to that button. For example numberOfTimesClicked etc. I am currently working with GridViewColumnHeader and I would like to add the property columnIndex to that class. I know I can keep track of the columns with other methods but I am just curios to know if we can add extra properties to classes. For example I was thinking about inheritance. If I create a new class and inherit from the class that I want to add new properties (in my case GridViewColumnHeader) then I think that should work but for some reason I get errors in my code whenever I do something like:
private class MyGridViewColumnHeader : GridViewColumnHeader
{
public int propertyThatIWantToAdd { get; set; }
}
from now on if I instantiate objects from MyGridViewColumnHeader class instead of GridViewColumnHeader class I get errors. What is wrong with using inheritance to achieve this?
Instead of casting the sender object use
e.OriginalSource as MyGridViewColumnHeader
And do your work on that object. If you need to know what is inside the RoutedEventArgs have a look on MSDN
You should make the class public, the private modifier is only allowed for inner classes.
Also you should use Dependency Properties instead of normal Properties, if you want to access the property in XAML.
I was trying to implement a specialized collection that works like ObservableCollection to encapsulate some more mechanisms in it, to do that i also let my collection inherit from Collection and i also implement the same interfaces.
I just do not get though how one actually implements the whole collection-changed-logic, for example Collection<T>.Add is not being overridden (it is not even marked as virtual), so how does the ObservableCollection fire the CollectionChanged event if items were added using that method?
To answer your specific question, Collection<T>.Add calls the InsertItem virtual method (after checking that the collection is not read-only). ObservableCollection<T> indeed overrides this method to do the insert and raise the relevant change notifications.
It does so by calling InsertItem which is overridden and can be seen upon decompilation
protected override void InsertItem(int index, T item)
{
this.CheckReentrancy();
base.InsertItem(index, item);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
Remember, the key is not in overriding the base Collection methods, it's in the fact that you will be implementing the ICollection interface. And frankly, rather than inheriting from a Collection class, I would suggest instead creating an adapter class that takes a ICollection in the constructor and your methods will just delegate to the inner collection and raise the appropriate events.
If you frequently use in your program a collection which path would you prefer:
Type List<T> everywhere.
Define class:
class TT:List<T>
{
}
Define class:
class TT
{
private List<T> _tt;
// ...
}
I think it's not very important, but after last project I started to think about it very often.
You should only create your own collection class if it will add additional functionality.
When you do create your own collection classes, you should inherit from the System.Collections.ObjectModel.Collection<T> class, not List<T>.
Inheriting this class allows you to override InsertItem and RemoveItem and run custom logic when the collection is modified. (This is not possible when inheriting List<T>)
You can use any option you specified depending on what you need:
(1) if you need to use list and type of the collection won't be changing.
(2) if you want to extend your collection with additional functionality then your should use inheritance.
(3) if you need to create additional level of the abstraction. In the this case your collection would be only implementation detail, e.g. you will be able to change list on the set in the future.
If I just need a list, I use 1. If I want to add additional methods and limitations, I will define 2.
Don't subclass List<> -- that's almost invariably a symptom of incorrect abstraction. Let a List be a list, nothing more. I don't have any idea why you'd want to use your 3rd option.
Like everything, there are tradeoffs. The benefit of using a wrap class (encapsulating) your list is to militarize access to it. It means a lot of work:
You will have to add specific methods to add and remove from the list
You will have to add the iterator methods and might end up modifying syntax when iterating.
All these costs must serve a purpose. You'd do it if you want to intercept insertions and removals from the list, or if you want to create your own methods to filter the list and such. Maybe you need a immutable list. Make sure you have enough reasons to go through the trouble of creating the wrapper class.
Finally, as SLaks has put, it's better to inherit Collection<T> than to wrap around a list. I don't know the real differences, but I'd with this alternative.
I have a class I am working with:
public sealed class WorkItemType
It's ToString is weak (Just shows Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemType).
Is there any way to override this to show the name of the WorkItemType?
Normally I would just aggregate the value in a new class, but I am using this for bindings in WPF (I want to have a list of WorkItemTypes in a combo box and assign the selected value to a bound WorkItemType variable.)
I think I am out of luck here, but I thought I would ask.
A fairly neat way to do it might be to add an extenesion method to the WorkItemType object. Something like this:
public static class ToStringExtension
{
public static string MyToString(this WorkItemType w)
{
return "Some Stuff"
}
}
Then you could call something like
WorkItemType w = new WorkItemType;
Debug.WriteLine(w.MyToString();)
Do you need to override ToString? If you are in control of the code where the object is displayed, you can always provide a FormatWorkItemType method, or something to that effect.
WPF provides a few different built-in ways to do this right in the UI. Two I'd recommend:
You can use ComboBox's
DisplayMemberPath to display a single
property value but still select from
the WorkItemType objects.
If you want to display a composite of
a few properties you can change the
ComboBox's ItemTemplate to make it
look pretty much however you want -
formatting text, adding borders,
colors, etc. You can even set up the
DataTemplate to automatically be
applied to any WorkItemType object
that gets bound anywhere in your UI
(same basic effect from UI
perspective as changing ToString) by
putting it into Resources and giving
it only a DataType with no x:Key.
You're out of luck :-(
You could write your own class that wraps the WorkItemType and delegate down to it (a proxy) expect for the ToString:
class MyWorkItemType
{
private WorItemType _outer;
public MyWorkItemType(WorkItemType outer)
{
_outer=outer;
}
public void DoAction()
{
_outer.DoAction();
}
// etc
public override string ToString()
{
return "my value"
}
}
I don't have any C# knowledge, but can't you wrap your extended class inside another class? Proxy all method calls to the extended class, except toString(), Also very hackish, but I thought I'ld bring it up anyway.
Doing some sorta magic with reflection is probably your only hope. I know you can instantiate private constructors with it, so maybe you can override a sealed class... Note, this should be your last resort if there is seriously no other way. Using reflection is a very hackish/improper way of doing it.
In addition to the other WPF-specific answer you could use an IValueConverter in the binding to format / display the WorkItemType however you want. This has an advantage of being reusable (if you want to display the object in some other control, for instance.)
There are many examples of using converters here. This other question should be pretty similar to the ComboBox usage mentioned here. The answers note that you can either make the converter work on the entire collection of objects, or work on one item at a time. The latter might be the more reusable approach.
Recently I used a class that inherits from a collection instead of having the collection instantiated within the class, is this acceptable or does it create unseen problems further down the road? Examples below for the sake of clarity:
public class Cars : List<aCar>
instead of something like:
public class Cars
{
List<aCar> CarList = new List<aCar>();
}
Any thoughts?
The problem with this is that your Cars class will still have the interface it inherits from List, which may allow operations you don't want.
That depends on the final purpose of your class. If it is only going to work as your own implementation of a collection use inheritance. If not, include a a collection as a property. The second option is more versatile:
As you can only inherit from one class, you might need to inherit from another class rather than collection
If you need to see this class as a collection you can include an indexer property.
I misread the question previously.
I would suggest using composition instead of inheritance. If you want to be able to use all the funky LINQ stuff, by all means implement IEnumerable<T> and perhaps even IList<T> - but I wouldn't derive from List<T> directly.
If you do want to get the collection stuff "for free" but still retain control, you could use CollectionBase. That still ties you down in terms of your one shot at inheritance, but at least you get more control over what happens in the collection.
If you want your Cars class to act just like a List and to have the same methods than it isn't that bad. You just derive from it and you're done. Then if you want to add any additional functionality, you can just declare those methods and you're done. However, you're now bound to List and if List changes in any undesirable ways, you're screwed.
When you make it a composite class instead and have the List instantiated inside the class then you only need tp expose the methods of List that you want exposed. But that means that you have to repeat them all too.
If the purpose of the class is to add additional functionality to a standard collection, then I would inherit from the collection. If the collection is just one part of a bigger picture, then that sounds more like a property.
I would, however, consider using Collection<T> instead of List<T> unless you really need the functionality in List<T>.
Is the "Cars" class really required?
Has some added functionality than "List" ? If not, you should use "List" ( or better "IList" ).
If class "Cars" has any added functionality, there is two main scenarios:
This class is "final" class, there is no big possibility, the someone others need extended it. Then is this construction OK.
This class will be probably used as base class. Then I recommend use this construction:
.
public class CarList<T> : List<T> where T : Car {
// some added functionality
}
If you want be more flexible in future, you should use a composition:
public class CarList<T> : IList<T> where T : Car {
private IList<T> innerList;
public CarList() { this.innerList = new List<T>(); }
// implementation of IList<T>
// some added functionality
}