Using generic collections in Silverlight user controls - silverlight

There is an interface:
public interface IFoo {
}
A Silverlight user control has a collection of IFoo instances:
public ObservableCollection<IFoo> Items { get; set; }
There is an abstract class that implements the interface:
abstract public class Foo : IFoo {}
And a class that further derives from that:
public class DerivedFoo : Foo {}
With all of that said, I'm trying to add instances of DerivedFoo into the control's collection via XAML, but I receive an error that DerivedFoo is not of type IFoo and cannot be used in the generic collection.
I did find a post in a forum that said this was a bug in Silverlight 3 but would be fixed (I am using Silverlight 4). Is this still a bug or am I going about this incorrectly?
Update:
My code is at home and I'm at work so I can't post the actual XAML, but from memory it was along the lines of:
<my:Thing>
<my:Thing.Items>
<my:DerivedFoo ... />
</my:Thing.Items>
</my:Thing>

The answer is...
The CollectionChanged event handler for the generic collection made an improper cast during the Add action.

Related

SimpleMVVM and Generic ViewModelBase

I recently found the SimpleMVVM toolkit and am trying to create a small example program. I am trying to create a CurrentViewModel parameter like so:
private ViewModelBase<> _CurrentViewModel;
public ViewModelBase<> CurrentViewModel
{
get { return _CurrentViewModel; }
set
{
_CurrentViewModel= value;
NotifyPropertyChanged(m => m.CurrentViewModel);
}
}
Any object referenced by CurrentViewModel will extend the SimpleMVVM ViewModelBase class like so:
public class HomeViewModel : ViewModelBase<HomeViewModel>
{ }
The problem I am having is that SimpleMVVM ViewModelBase requires a type T as an argument and I don't know how to create the parameter CurrentViewModel such that it can accept any ViewModel extending ViewModelBase.
One of the issues around using Generics '<T>' is that any consumer has to still know the type. If you consider adding an ICollection to your model, you have to know what it is a collection of so that you maintain strong typing.
The only exception is if you define a class which is itself generic, which can then pass on it#s type property to a child class. i.e.
CustomCollection<T>
{
ICollection<T> _foo;
}
To do what you're trying to do will require a seperate common interface that encapsulates the functionality you want from CommonViewModel.

Using WPF design data with the MVVM pattern

I'm using the MVVM pattern in our WPF application to allow for comprehensive unit testing. The MVVM pattern itself is working great, however I'm struggling to adapt the pattern in a way that means I can use the design-time data support of WPF.
As I'm using Prism the ViewModel instances are generally injected into the constructor of the view, like so
public MyView(MyViewModel viewModel)
{
DataContext = viewModel;
}
Dependencies for the ViewModel are then injected into the constructor, like so
public class MyViewModel
{
public MyViewModel(IFoo foo, IBar bar)
{
// ...
}
// Gets and sets the model represented in the view
public MyModel { get; set; }
// Read-only properties that the view data binds to
public ICollectionView Rows { get; }
public string Title { get; }
// Read-write properties are databound to the UI and are used to control logic
public string Filter { get; set; }
}
This is generally working really well except when it comes to design data - I wanted to avoid compiling design-data specific classes into my released assembly and so I opted to use the {d:DesignData} approach instead of the {d:DesignInstance} approach, however in order for this to work correctly my ViewModel now needs to have a parameterless constructor. In addition, I also often need to change additional properties either to have setters or to be modifiable collections in order to be able to set these properties in XAML.
public class MyViewModel
{
public MyViewModel()
{
}
public MyViewModel(IFoo foo, IBar bar)
{
// ...
}
// Gets and sets the model represented in the view
public MyModel { get; set; }
// My read-only properties are no longer read-only
public ObservableCollection<Something> Rows { get; }
public string Title { get; set; }
public string Filter { get; set; }
}
This is worrying me:
I have a parameterless constructor that is never intended to be called and isn't unit tested
There are setters for properties that only the ViewModel itself should be calling
My ViewModel is now a jumbled mixture of properties that should be modified by the view, and those that shouldn't - this makes it tricky to tell at a glance which piece of code is responsible for maintaining any given property
Setting certain properties at design time (e.g. to see styling on the Filter text) can actually end up invoking ViewModel logic! (so my ViewModel also needs to be tollerant of otherwise mandatory dependencies being missing at design time)
Is there a better way to get design-time data in a WPF MVVM application in a way that doesn't compromise my ViewModel in this way?
Alternatively should I be building my ViewModel differently so that it has more simple properties with the logic separated out somewhere else.
First, I would recommend you to have a look at this video where Brian Lagunas provides several best practices about MVVM. Brian is - at least - involved in the development of Prism, as his name appears in the nuget packages information. Didn't check further.
On my side I only use bits of Prism, and my Model and ViewModel always offer blank constructors (like what Brian shows), the data context is assigned in the view's XAML, and I set the properties values like :
<MyView.DataContext>
<MyViewModel />
</MyView.DataContext>
and
public void BringSomethingNew()
{
var myView = new View();
(myView.DataContext as ViewModel).Model = myModel;
UseMyView();
}
Another benefit with this approach is that the ViewModel is created once, with the same path at design and run time, so you create less objects and save GC efforts. I find this elegant.
With regards to the setters, the design data will still work if you make them private, like:
public string MyProp { get; private set; }
Ok, customize it to manage NotifyPropertyChange at your convenience, but you've got the idea.
Now, I don't have yet a solution to manage ObesrvableCollections (I face the same problem, although putting multiple values in XAML sometimes work... ???), and yes, I agree that you have to manage the case when the properties are not set, like setting default values in the constructor.
I hope this helps.
I too have worked with NUnit testing with WPF and MVVM implementation. However, my version is reversed from yours. You are creating the view first, then creating the model to control it.
In my version, I create the MVVM model FIRST and can unit test it till the cows come home and not worry about any visual design... if the model is broken, so too will the visual implementation.
in my MVVM model, I have a method to "GetTheViewWindow". So, when I derive from my MVVM baseline, each view model has its own view its responsible for. So via a virtual method, each instance will do its own new view window when being applied for production.
public class MyMVVMBase
{
private MyViewBaseline currentView;
public MyMVVMBase()
{ // no parameters required }
public virtual void GetTheViewWindow()
{ throw new exception( "You need to define the window to get"; ) }
}
public class MyXYZInstanceModel : MyMVVMBase
{
public override void GetTheViewWindow()
{
currentView = new YourActualViewWindow();
}
}
Hope this helps as an alternative to what you are running into.

Access properties from one view model in another

My WPF application follows the MVVM pattern. There are three views:
MainWindow
LoginView
ProjectsView
LoginView and ProjectsView are user controls imported by the MainWindow. Both views have their view model assigned. LoginViewModel defines a property ProjectList which is set by calling a webservice. Now LoginViewModel needs access to the ProjectList property and others.
I am aware that one solution might be a redesign so that there is only one view and one view model. I would do that as a backup solution but I would favor not to do so.
How should this be done? Should I use some kind of EventAggregator like in Prism? Or are there other ways to do this?
So if i understood clearly, ProjectList property should be accessed from both 'LoginViewModel' and 'ProjectsViewModel'. I'd try to implement it in the 'MainViewModel' so child viewmodels can access it in a natural way.
An IEventAggregator is like a box in which you can add events, or find and subscribe to one, so i would say it's not what you need.
Anyway, you could register your custom interface (box type) in the UnitySingleton.Container, which would expose ProjectList for it to be accessible everywhere. This approach makes a lot of sense when modules, which are separate assemblies, need to communicate whith each other.
If this is overkill or not in your case is something you should decide, i'd personally go with the 'put it in the mainviewmodel' option.
-- Sample -- (not tested)
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
LoginVM = new LoginViewModel(this);
ProjectsVM = new ProjectsViewModel(this);
RetrieveProjectList();
}
public LoginViewModel LoginVM { get; private set; }
public ProjectsViewModel ProjectsVM { get; private set; }
public object ProjectList { get; private set; }
private void RetrieveProjectList()
{
ProjectList = ....
}
}
It's pretty simple as you see, LoginVM and ProjectsVM will hold a reference to the MainViewModel that created them, therefore giving them access to ProjectList.
How should this be done? Should I use some kind of EventAggregator
like in Prism? Or are there other ways to do this?
Here are a few ideas:
You can create a view-model class that both view-models
inherit from. This base class will contain the shared properties.
Create a static class that contains the shared properties.
Using dependency injection, create a class that contains the
properties, register it as a singleton in your container and inject
it into your view-model's ctors.
Also, I believe that the EventAggregator is best suited for communicating between modules/assemblies. In your example, it seems like everything is in the same assembly.

Winforms databinding with interface inheritance

I need someone to confirm what I am seeing before I may a change to the domain of the application because of this issue. The issue is that when databinding against interfaces that inherit from one another, you can not see the properties on the base interfaces.
I am working on a WinForms application that uses databinding. This is in .net3.5 and no I can not use wpf.
Anyways, I have a setup something like this.
public interface IClassOne
{
string Prop1 { get; set; }
}
public interface IClassTwo : IClassOne
{
string Prop2 { get; set; }
}
public abstract class ClassOne : IClassOne
{
public string Prop1 { get; set; }
}
public class ClassTwo : ClassOne, IClassTwo
{
public string Prop2 { get; set; }
}
The base class would hold common properties and logic. The base interface would have those common properties on it so they would have to be implemented on each concrete implementation.
If I was databinding to my class structure above, I would be binding to IClassTwo. The problem is when I databind to IClassTwo, I can not see Prop1 in any of the designer operations for WinForms. Even if I get around that limitation and get a control to be bound to Prop1, it does not work.
However if I bind two ClassTwo, then databinding works.
I do not want to deal with the concrete classes because that would make using mocks and testing too hard. I also do not want to put everything on IClassTwo because I would have to repeat code when I make another concrete implementation.
What I need to know is if this truly doesn't work. If you know why, that would be a bonus.
Thank you
Tony
http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/4151e6b6-44f7-45e2-9a8e-92c4f8539095/?prof=required
Here is a snippit of what is posted on MSDN as to why this doesn't work. The poster who wrote this goes by "franking".
No, it's not possible to bind to an interface! BindingSource offers some help to use a type as data source. Internally it will instantiate a BindingList<> instance using the type information. Also adding new items will work, but AddNew() will fail unless you subscribe the AddingNew event.

MVVM Mediator multiple instances

Can someone explain how the mediator pattern works with multiple instances.
My code in the view:
public MyView() {
Mediator.Register("CloseWindow",()=>Close());
}
and in the ViewModel:
public SomeMethod() {
Mediator.Notify("CloseWindow");
}
This works find as long as there is only one instance of the View - ViewModel pair.
How do I solve it with multiple instances?
I use an alternative solution. MyView implements an interface IMyView which contains the Close method. The MyViewModel object associates the View and so it can call the Close method through the interface.
If you are interested in a concrete example then you might have a look at:
WPF Application Framework (WAF)
I don't know how your particular implementation of the mediator pattern works, but in mine you can send more information than just strings.
For example:
public MyView() {
Mediator.Register<CloseWindowMessage>(message =>
{
if (message.ViewModel == DataContext) Close();
});
}
and in the ViewModel:
public SomeMethod() {
Mediator.Notify(new CloseWindowMessage(this));
}
In this example, the ViewModel passes itself as a parameter to the view. The view can then check that the message is being sent from its view model.

Resources