MVVM practices: expose viewmodel class inside a control - mvvm

I've edited the question to make what I want to obtain clearer.
Here's the original question:
I'm working on a class that inherits from Control which will be used in my View and includes some Dependency Properties.
One of these DPs is an IEnumerable(Of RfidTag) and will be bound to an ObservableCollection(Of RfidTag) inside the VM.
The class RfidTag is defined as public class in the same file where the VM's class resides.
The questions are:
1. is it a good practice to expose a VM-related class to a Control class?
2. is the VM source file a good place for the RfidTag class?
UPDATE 1
In my application logic (I think I could say in my Model) there is an event published throught an Eventaggregator. The event's payload is a List of ModelRfidTag (that is the model class).
My VM subscribes to this event and I made the RfidTag class to wrap my Model class and provides some additional properties related only to the VM.
When the event handler inside the VM is executed, it makes an ObservableCollection(Of RfidTag) bindable from the view.
Then in the View I've a bounch of my control instances like that
<c:RfidTagPresenter
TagPosition="1"
Collection="{Binding RfidTagList, Mode=OneWay}" />
Then in my RfidTagPresenter (the class that inherits from Control) I've a DP of type RfidTag (called RfidTagResult) that returns the object in the OC which has the Position property (property available inside the RfidTag class) equal to the value set by the TagPosition DP.
In this way, the ControlTemplate of the RfidTagPresenter can bind its elements to the desired object.
This is the simplification of what I want to make. In the actual application there are some other DPs on which the RfidTagResult selection is performed
UPDATE 2
After a bit of research, seem that I can solve one problem with an indexed property that return (in the get method) the object from the collection I want to bind.
However a problem still exist: My control need to have a DP of type of RfidTag so that the relative ControlTemplate can bind to the property declared in the RfidTag class.
So: Is it possible (read: a good practice) to have a DP of a type that is a VM related class?
In other words: Can a custom control know about the class type used by the VM?

I will try to go all over your question (if I miss something let me know) but first you should explain the purpose of binding a Collection in a control as a DP.
is it a good practice to expose a VM-related class to a Control class?
RfidTag, I suppose, is a Model. What you are really doing here is binding a Model in your control which go against the MVVM pattern. You should think about the next question... Do you really need all your RfidTag to be shown in the View ? If you need to show a name, an ID... you could just create an IEnumerable<string> as DP (which is correct) and then in your VM instead of an ObservableCollection<RfidTag> you would have an ObservableCollection<string>.
Some simple theory. In MVVM, VM adapts the Model to the View. So your VM should have everything that will be shown in your View.
is the VM source file a good place for the RfidTag class?
RfidTag is a Model so there's no better place for it :)

Related

Using Zenject to inject an implementation with interfaces

I'm trying to use Zenject in Unity. I have an interface and several implementations of it.
I want to inject with ID but also that the implementation will have the tick interface since it's not a MonoBehaviour.
So I have an IAttacker interface and a MeleeAttackImpl implementation.
Container.Bind<IAttacker>().WithId(AttackerTypeEnum.MELEEE).To<MeleeAttackImpl>().AsTransient();
I want to add
Container.BindInterfacesTo<MeleeAttackImpl>().AsTransient();
But it creates 2 different objects instead of instances that have the Tick interface and bind them to IAttacker.
If you want to bind an interface to a determined implementation, why do you use two bindings?
If you want only one instance of the object I would try:
Container.BindInterfacesAndSelfTo<MeleeAttackImpl>().AsSingle();
or:
Container.Bind<IAttacker>().To<MeleeAttackImpl>().AsSingle();
As Single() In the case you need the same instance provided from the container along the app (like a singleton).
From the documentation:
"AsTransient - Will not re-use the instance at all. Every time ContractType is requested, the DiContainer will execute the given construction method again."
Many times intance is created in the binding itself. So maybe from the two binding two instances are created, one from each binding.
In case you need to create instances dynamically with all their dependencies resolved, what you need a is Factory.

Number of converter instance for binding in UWP

How many instance does binding creates internally for converters.
<Image x:Uid="DisplayedImageUrl" Style="{StaticResource ImageStyle}"
Source="{Binding DisplayedImageURL, Converter={StaticResource ImageLogoConverter}}" />
How many instance does of ImageLogoConverter will be there?
Is it good idea to use converter in ViewModel, if not then what is the best way to access converted value of ViewModel property.
Is it good idea to use converter in ViewModel?
No. Why would you use a converter in a view model where you can return the converted value directly? Converters are used in the view, typically to convert a non-view friendly value that the view model returns.
If not then what is the best way to access converted value of ViewModel property?
You can simpy return an already converted value from the view model, i.e. instead of binding to a Uri property, you may bind directly to an ImageSource property.
This is the recommnded approach if you for example intend to display a lot of elements in a ItemsControl. Then you probably don't want to invoke a converter for each visible element for performance reasons.
I suppose you created the converter as a resource like this:
The number of instances now depends on the scope where the converter resource is declared. If you create it in <Page.Resources>, one instance will be created to be used by the page. If you create it in App.xaml in <Application.Resources> it will be an application-wide instance. Of course, you can even use a narrower scope - create it as a resource of a single control in your XAML tree for example - in any case, a single instance is created when instance of the parent is created.
The situation gets a bit more interesting if you embed it in a ItemTemplate of a list control. Thanks to virtualization, the system will not actually create one instance for each item. Instead, it will create only so many instances as fit on the screen and they get reused when the user scrolls.
Some MVVM developers don't like value converters, but others use them extensively. It really is a matter of preference. In cas you expect the underlying data to change often, it is advisable to keep the code in the converter as performant as possible as it runs on the UI thread.

MVVM: Should a ViewModel have a member to another ViewModel?

The dependent ViewModel gets injected via the constructor (IoC container).
Example: ProductSelectionViewModel uses ShoppingBasketViewModel.
Is this a common practice or is this THE recommended way? I don´t think so...
How should it be done right?
Should the view use the 2 ViewModels?
Mediator pattern?
Event driven?
Personally I don´t like the last one.
There's nothing wrong with a view model having a direct reference to another view model, if it is a required dependency, then injecting it via the constructor is fine.
If you wish for a view model to be able to create new instances of another view model, then injecting a view model factory type would be the way to go.

Approach for binding on a MVVM application using Portable Class Libraries

I'm trying to port the core of an application across to Portable Class Libraries and don't appear to have binding support.
I'm trying to bind a property on my ViewModel to my Model, which consists of an ObservableDictionary (INotifyPropertyChanged, INotifyCollectionChanged, IDictionary<string, string>). I do this usually (with WP7) by using the following code when initialising the view model:
SetBinding(MyProperty, new Binding(string.Format("MyDictionary[{0}]", "thekey")) { Source = MyModel });
How would I approach this when using Portable Class Libraries, where it seems like the Binding class is unavailable?
I've implemented this by having the base class for the ViewModels wire up to the PropertyChanged event of the ViewModel and the NotifyCollectionChanged event of the ObservableDictionary. I then have a method (with a set of overloads for additionally supplying an implementation of an IPclValueConverter which is a copy of the IValueConverter) which adds to a collection of PclBinding objects which is a set of PropertyInfo, dictionary key, IPclValueConverter and a converter parameter.
Within the PropertyChanged/NotifyCollectionChanged I check to see if the binding should be updated, and if so perform the update passing the value through a converter if present.
This means that from my original example, I now write the following inside my ViewModel which creates the binding as required:
SetBinding(() => MyProperty, "theKey");
If anyone is actually interested in this code I'd be happy to post it up. :)

Wrapping my mind around MEF: how to load View(Model)?

I'm learning prism V4 using MEF to load my modules. Loading modules does work, but in one module I want to load a View/ViewModel (MVVM) and don't really know how I get MEF to resolve all this stuff for me.
First: how do I need to mark the ViewModel (I follow the StockTraderRI example) so it is not loaded on startup but instead can be loaded during runtime into a region?
Second: how do I load the ViewModel using MEF so it gets connected to the corresponding interfaces?
MEF does this very nicely for things on startup which are marked as [Export], but I got no idea how to achieve this during runtime.
You can use what is known as a Lazy Export so that the interface is not resolved until you explicitly use it.
If you need to create multiple instances, MEF doesn't support this particularly well. You can either do your own discovery and instantiation, or you can define the Export like this:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(ISomething)]
public class Something : ISomething { }
The downside is that now wherever you need to create the instance, you need to have a reference to the actual Container instance. Then you can do:
var something = _container.GetExportedObject<ISomething>();
EDIT: Okay, I think I understand better what you're after. Here is how I've typically resolved this issue:
I implement my View objects as UserControl instances and don't set a DataContext anywhere in their code or XAML.
I create a DataTemplate that binds from the Type of the ViewModel to the UserControl.
On my MainViewModel (or whatever corresponds to the View hosting the regions), I expose a general RegionX Object (possibly typed to an interface if all of my ViewModels will share some common functionality, but Object works fine).
I create a ContentPresenter with Content bound to the RegionX property.
Now my MainViewModel can import different ViewModel instances corresponding to the types of ViewModels that might be hosted by the RegionX. When I want to switch the 'active' View in the region, I simply set RegionX to the corresponding ViewModel.