I'm building an Silverlight application which consists of a grid containing multiple different widgets. Each widget is implemented as a ViewModel class which are then binded to grid.
With WPF I'd use implicit DataTemplates to bind certain ViewModel to a certain View. But since Silverlight doesn't support this feature I'm a bit stuck.
So far I've only thought of implementing some sort of global DataTemplateSelector to which each Prism module would register matching ViewModel and View pairs at startup. Then I could use Unity to inject this selector to grid and achieve what I want but this doesn't feel like the best way to do it.
Any ideas how should I do this?
I did some more googling and found few articles about TemplateContentControl (e.g. http://blogs.microsoft.co.il/blogs/arielbh/archive/2010/10/24/how-to-develop-mvvm-silverlight-applications-with-prism.aspx) and after some testing it seems to be just what I was looking for.
Check out the DataTemplateSelector for Silverlight.
Read about it more here.
Related
I need help with a change of perspective.
I got stuck trying to approach UWP in a way I used to do in WPF regarding a MVVM pattern for managing UserControls dynamically.
I naturally tried to perform the same pattern in UWP but got stuck on various things like UWP not supporting 'x:Type' ...
Situation is; time to rethink this approach and look for a new direction. Seems I'm forced to abandon to use implicit binding in a similar fashion to the WPF pattern, using the Content property of a ContentPresenter and a VM property 'of type Object', which maintain a selected ViewModel. It was a simple and clean approach for matching up the correct View automagically with the VM set in ActiveViewModel.
the below was such a simple way of managing many views all over the place, odd MS not fixing this? But, back to the big Q: what now in UWP!?
<ContentPresenter Content="{Binding ActiveViewModel}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:OneViewModel}">
<local:OneView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:TwoViewModel}">
<local:TwoView />
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
What Shall I do instead of this!? Anyone found a new efficient way of doing it? I got stuck in my stubborn mind and need someone to kick my butt so I go forward. Getting to old to change, but due to this profession it seems I constantly have to. :)
Looking at the DataTemplate documentation, there's a paragraph explaining the situation which you are trying to figure out.
For advanced data binding scenarios, you might want to have properties
of the data determine which template should produce their UI
representations. For this scenario, you can use a DataTemplateSelector
and set properties such as ItemTemplateSelector to assign it to a data
view. A DataTemplateSelector is a logic class you write yourself,
which has a method that returns exactly one DataTemplate to the
binding engine based on your own logic interacting with your data. For
more info, see Data binding in depth.
Here, you have an example on how you can select distinct DataTemplate for items in a control such as a ListView based on defined conditions.
Your situation is a bit different from the one described above, but the solution should be within what is explained above.
Create a class which derives from DataTemplateSelector, and override the SelectTemplateCore methods exposed by it, where you define the logic of what DataTemplate should be selected for the specific presented object.
This Derived class should expose properties of type DataTemplate, which identify each single DataTemplate template object, you pretend to be able to choose from.
Just as in the example, you are probably better of by defining the DataTemplate resources on an higher level object, such as the Page itself.
Instantiate your DataTemplateSelector Derived class in XAML as a resource and set each of the properties exposed above of type DataTemplate to the analogous DataTemplate static resource.
Utilize the ContentTemplateSelector dependency property, by setting it your custom DataTemplateSelector.
With this logic, it should be possible to have your ContentPresenter decide correctly between which DataTemplate it should choose from, based on your required UI logic.
In a WinRT Page how can I inject dependencies?
I am thinking of doing something like this:
/// <summary>
/// A page that displays an overview of a single group, including a preview of the items
/// within the group.
/// </summary>
public sealed partial class MyPage : NSyncApplication.WinRT.Common.LayoutAwarePage
{
IMyDependency _myDependency;
public MyPage(IMyDependency myDependency)
{
_myDependency = myDependency;
this.InitializeComponent();
}
.
.
.
}
If this isn't a good practice please explain and recommend an alternative solution.
Note:
I don't need the specific DI containers that can be used with WinRT, that's been answered already and any idiot can look at nuget gallery and pick their choice.
This question is about how I can plug into the Page factory and inject my own dependencies. I have also looked at Prism for WinRT and that thing is even more convoluted than I remember the WPF version to be.
To repeat:
How can I inject into the page directly. Is there a page factory
or something that I can tap into to add custom instantiation code?
Should I inject to the code behind and make it a viewmodel? The Prism MVVM example had
another layer of abstraction for the ViewModel separate from the
code behind (which's considered part of the View). This is nice and cool, but requires more wiring and
custom mark ups than I care to do for my relatively simple project. I am hoping to roll with something more "light-weight". But may be there's an argument to be made against that, please explain.
Please, check MVVM-Light. They use VMLocator which exposes view models to which XAML can bind. On MSDN Magazine you can find an example of how to use it.
I have a usercontrol that i want to use throughout my Silverlight MEF MVVM solution.
I want to be able to link it up with one of a number of ViewModels depending on which module i am in. What this control does is list the records of a given entity so i can Add, Edit or Delete. I realized i would be using this control in multiple locations - to update several lookup tables, so i decided to make it's ViewModel dynamic. As seen below, I am using the Galasoft MVVM plugin.
if (!GalaSoft.MvvmLight.ViewModelBase.IsInDesignModeStatic)
{
// set DataContext
DataContext = PluginCatalogService.Instance.FindSharedPlugin(ViewModelTypes.ViewModelMT, PluginType.ViewModel);
_viewModel = (ViewModelMT)DataContext;
}
My question is how can i dynamically change from ViewModelMT to ViewModelCT to allow me to independently display lookup tables e.g. Maintenance Types and Contract Types on an instance of this same usercontrol? I took a look at the Viewmodel locator, but I'm still not sure how to get this done.
Thank you
I don't think this is really a ViewModel thing. It's more of a Service problem.
Your ViewModel for the control will not change but you'll dynamically slot in the required service to maintain your list. ie. MaintenanceTypeService and ContractTypesService will implement IListMaintenanceService which exposes an list of items and Add,Delete and Edit commands.
As the question suggests I'm simply looking for a XAML tag list reference. I've banged the obvious queries in Google/SO but not found what I am looking for yet. Any useful links welcome.
There's a WPF Binding Cheatsheet and another XAML for WPF Cheatsheet which might help, but really the "tags" in XAML are just the properties of the classes.
There isn't such a thing as a xaml tag list.
XAML is just a declarative way to instantiate .Net classes. Class names are elements in XAML and properties on the class are attributes or attribute elements using dot notation.
Tags in XAML only mirror the types in one or more assemblies that are bound to a particular XAML namespace.
There are however a specific set of elements that are specific to XAML in itself and are not related to any particular .Net assembly, those are usually in the x: namespace, more info here: XAML Namespace (x:).
There is no such thing as the XAML tag list since XAML is an open system.
There are, however, standard vocabularies. Rob Relyea's Blog is a good place to keep track of the standardization around these vocabluaries. For example, this is an entry for the Silverlight XAML vocabulary.
With WPF the XAML elements map to the classes like StackPanel. MSDN seems to give XAML examples for many of the controls.
There are XAML-specific conventions about representing things like complex properties and bindings. However, there is no definitive list of XAML tags. XAML tags are actually mapped to WPF objects. For example, <Button> is just a XAML representation of the System.Windows.Controls.Button class and the attributes allowed on the <Button> tag are the public properties of the Button class.
There should be several WPF cheatsheets available soon on http://www.devsheets.com (since around September 2011) ... You can download it there, and also buy printed versions with more detailed information on them (not all content fits in publicly available pdf, because pdf would not be readable if printed on paper without high quality print ... that is why we also decided to sell high quality laminated cheatsheet prints in addition to their free versions)
If I have a usercontrol (in Silverlight) that I've written, that uses XAML to define it's appearance, how can I make a customised version of it?
i.e. I have MyControl.xaml & MyControl.xaml.cs
What do I need to do if I want a "SpecialisedControl" child class? I assume I just make a new code file, then inherit from MyControl. But what if I want to change the appearance of the base class - then what do I do?
I wrote this thinking you were talking about WPF, rather than Silverlight, but there may be enough overlap for this to be helpful, so I'm posting it, anyway.
If by "change the appearance of the base class" you mean "provide a new template", then what you need is probably a CustomControl, not a UserControl.
The best way to accomplish this is to follow the example set by other Microsoft controls, such as Button or ListBox:
Create a class that derives directly from Control (or whatever is closest to your control).
If any properties will need to be exposed to the control (such as text on a button, for example), make sure that you properly define them as DependencyProperties.
As described here, create a ResourceDictionary called Themes/generic.xaml and add a style for your class that includes a template (don't give the style a key).
Use TemplateBindings for any properties of elements on your control that need to get values from your control.
If you'll need to attach any event handlers to elements in your template, give them a unique name. Microsoft uses the convention of prefixing these names with "PART_", and I think it's a good thing to do for the sake of consistency, but it's not strictly required.
Again, if you need to attach event handlers, overload OnApplyTemplate(). In this method, you should detach any old event handlers (we certainly don't want any memory leaks!), and look for elements that have the names your provided in your template--when you find them, attach event handlers, as necessary.
This is certainly much more work than simply deriving from UserControl, but if you want to be able to totally re-template controls, like you can with the built-in controls, this is the way to do it.
On the other hand, if all you want to do is to provide a certain amount of limited customization, such as changing the background, or associating a Command with some user action, then the best thing to do is to expose DependencyProperties, which can then be set in styles for your control, or on instances of your control, itself.
In the case you mentioned of wanting to customize the look in an inherited control, the process is pretty similar: just add a default style for the new control with a new template; if you need to add more event handlers, just be absolutely certain that you call base.OnApplyTemplate().
I dunno, I like doing things with just plain objects. Here's an article that describes an easy way to slip a XAML-designed control outside your inheritance hierarchy so that you can customize appearance and behavior using SimpleThingsLikeInheritance rather than MicrosoftStuffThatAlmostWorks
http://gen5.info/q/2009/02/10/subverting-xaml-how-to-inherit-from-silverlight-user-controls/
As Mihnea's link describes, the easiest solution is to simply add a namespace in your XAML:
C#
public class MyBase : UserControl
{
}
public class FirstUserControl : MyBase
{
...
}
XAML
<local:MyBase
x:Class="FirstUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="YourAssembly" ...>
<!-- Sticking with UserControl instead of local:MyBase makes this clearer -->
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
..
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
..Your XAML
</local:MyBase>
You can solve this by using a wrapper as described in the link above.
But you can also use the strategy pattern to solve this problem.
In this post I explain how you implement these two methods.
http://www.lab101.be/2008/07/silverlight-usercontrol-inheritance/