Number of converter instance for binding in UWP - mvvm

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.

Related

AEM - How to pass data to a component

Usually an AEM component is retrieving its data from a JCR node, but I was wondering whether it's possible to pass data to it in HTL. Sure, there's data-sly-resource, but as far as I know this way you can only pass a JCR node.
So in an actual case I've got data in a model that's retrieved from elsewhere. Yet I'd like to use existing components. I'm aware that the data must at least match the component-types' model.
But what if the component I'd like to use is using an model that got its data injected like
#Inject
#Optional
String[] itemList;
So in my stubborn thoughts it should be possible to somehow pass a string array like
<div data-sly-resource="${myModel.aStringArray # resourceType='my/component' }"></div>
But like mentioned above this seems to be meant for passing nodes only.
Is there any way to accomplish passing data directly to a component (other than creating a template)?
You can pass additional information in the form of request attributes or selectors
Selectors
Selectors are the most straight forward of passing simple information. This is an array of strings that can be passed. This is quite useful to data that can act as flags ex:
Variant/Mode of the component
index of the component in a list if it is being included in a loop.
ID of the parent when building things like accordion, tabs
This approach is an abuse of selectors, but IMHO as long as you know what you are doing this shouldn't be a major concern.
<article data-sly-resource="${'path/to/resource' # selectors=['s1', 's2']}"></article>
You can add, replace or remove selectors while including the component. Checkout the documentation for the syntax. https://docs.adobe.com/content/help/en/experience-manager-htl/using/htl/block-statements.html#resource
Request Attributes
This option allows you to add custom request attributes to the component request. This can be used to pass objects as parameters to the component while including them.
These are standard http request attributes with convince of scoping them to a particular instance of script/resource inclusion. To use this you will end up needing a model class or use-js as there is little support to compose the data to be passed along in sightly.
<sly data-sly-use.settings="com.adobe.examples.htl.core.hashmap.Settings"
data-sly-include="${ 'productdetails.html' # requestAttributes=settings.settings}" />
https://docs.adobe.com/content/help/en/experience-manager-htl/using/htl/block-statements.html#request-attributes
There is another way. You can pass additional parameters to the Sling Model on initialization using data-sly-use. For example:
<div data-sly-use.model="${'com.model.Teaser' # test='abc'}"
You can read then the variable "test" in model from request:
#PostConstruct
private void initModel() {
String value = request.getAttribute("test");
// value is 'abc'
}
In order this to work correctly you need to make sure your Sling Model is adaptable from request #Model(adaptables = SlingHttpServletRequest.class}

MVVM practices: expose viewmodel class inside a control

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 :)

Structural design pattern for MVVM View Model?

Are there any recommended structural design patterns for MVVM view models that allow different state and functionality to be added to a base object dynamically, but still maintaining the INotifyPropertyChanged on all the related properties? Something like a decorator pattern but mvvm-ready?
Yes. The WPF binding system will use a custom type descriptor to interact with the properties of your ViewModel at runtime. I've used this before to make keys in a KeyValueCollection<T> appear as properties on the collection.
This has two important benefits. It simplifies binding:
DataContext.SomeCollectionProperty[SomeKey] can be simplified to DataContext.SomeCollectionProperty.SomeKey and, if you make a custom type descriptor for the data context, DataContext.SomeKey which is about as simple as it gets.
And it fixes what I consider a bug--format strings are rendered even when the property is null. Using a CTD, you can skip null (and DBNull) properties, ensuring that format strings won't be rendered if the property doesn't exist:
Imagine you have a double? that you must render as a dollar amount. If you use the following binding: {Binding Price, FormatString='Price: {0:c}'} and the Price is null, you get the following in your UI: Price: $. This is ugly. However, if Price is a PropertyDescriptor-based property on your UI, when the Price is null, you can opt to not to report this property via your CTD. This prevents the format string from being rendered at all.
Here's a pretty good link at MSDN about decorating your types with a CTD.
From my experimentation, you can use the ExpandoObject in .NET 4 to handle what you want. ExpandoObject implements INPC. I've been creating a DynamicViewModel based on the ExpandoObject that does a few other things like calculated Properties that have dependencies on each other and Delegate Command registration.

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.

Setting a dependency property's default value at design time in a Windows Workflow Foundation Custom Activity

I'm implementing a Custom Workflow and Activities to be reused in multiple projects and trying to get them to be as easy to use as possible. In this workflow I have a Property whose name is 'UserID' which I'd like to bind to a dependencyproperty in one of my activities. I can currently bind it at design time searching explicitly for the property each time I add one of these activities to the workflow, but I'd like for this activity to be binded automatically.
As far as i know (correct me if I'm wrong), to bind a dependency property at design time I need to specify a string of the form "Activity=NameOfWorkflow, Path=UserID" to the DefaultBindingProperty metadata tag, and I'd like the name of the workflow to be completed in some way. Any way of doing this?
Thanks
I finally managed to achieve this by attaching an ActivityToolboxItem to the Activity, and overriding a method in it that creates the instance shown in the designer. I used an ActivityBind object to bind the dependencyproperty to the workflow's property. To get the instance of the workflow, I just searched for an ancestor to my activity by calling act.Parent until the activity had no parent (and thus was the StateMachineWorkflowActivity itself)