Silverlight 4 DataTemplate DataType

Silverlight 4 came out, and it looks like we again lost the DataTemplate DataType functionality in this release, which is pretty important for MVVM IMHO support. For my WPF applications, at the moment I'm pretty used to adding DataTemplates globally for my views in my application. Resources with DataTypes for my respective ViewModels:

t

<DataTemplate DataType="{x:Type viewModels:myViewModel}"> <views:myView/> </DataTemplate> 

I like this approach, since all my linked ViewModels automatically display the correct content ... especially useful when I have some ItemSource in my view tied to the ViewModels collection ... This, for example, will automatically check every tab in TabControl. associated with Collection<SomeViewModel> , displays the view associated with SomeViewModel .

Some things I tried for SL 3 include:

  • Create a "DataTemplatePresenterContentControl" that automatically applies the DataTemplate to Content when the control has loaded

  • The use of TypeConverter, dynamically applied under control load, goes along the visual tree looking for data-bound objects

  • Using the style applied dynamically to the control load goes along the visual tree looking for data-bound objects.

However, none of these approaches can really solve the problem that I mentioned above, which is really the key.

So, since this is still not possible out of the box in Silverlight 4, I would appreciate it if anyone else came up with some reasonable alternatives.

Thanks.

+6
silverlight mvvm datatemplate
source share
2 answers

The way I do it in several commercial projects is as follows:

I have a standard IValueConverter

 public class ViewTemplateChooser : IValueConverter { /// <summary> /// Modifies the source data before passing it to the target for display in the UI. /// </summary> /// <returns> /// The value to be passed to the target dependency property. /// </returns> /// <param name="value">The source data being passed to the target.</param><param name="targetType">The <see cref="T:System.Type"/> of data expected by the target dependency property.</param><param name="parameter">An optional parameter to be used in the converter logic.</param><param name="culture">The culture of the conversion.</param> public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is MyViewModel) { return new MyView { DataContext = value }; } return value; } /// <summary> /// Modifies the target data before passing it to the source object. This method is called only in <see cref="F:System.Windows.Data.BindingMode.TwoWay"/> bindings. /// </summary> /// <returns> /// The value to be passed to the source object. /// </returns> /// <param name="value">The target data being passed to the source.</param><param name="targetType">The <see cref="T:System.Type"/> of data expected by the source object.</param><param name="parameter">An optional parameter to be used in the converter logic.</param><param name="culture">The culture of the conversion.</param> public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

Converter will require namespace registration

 xmlns:Converters="clr-namespace:YourProject.Converters" 

Then you refer to the converter in the resources section:

 <UserControl.Resources> <Converters:ViewTemplateChooser x:Key="TemplateChooser" /> </UserControl.Resources> 

and finally, I use the converter to convert the ViewModel into a view with the Datacontext of the view set in the ViewModel

 <ContentControl Content="{Binding Workspace, Converter={StaticResource TemplateChooser}}" Margin="5,35,5,5" Grid.Column="1" /> 

The converter can be modified to implement navigation strategies, I tried to make the example as simple as possible.

Hope this helps, you don’t need to go to extremes - or third-party libraries - to get what you are looking for.

+8
source share

In WPF and Silverlight, I use Prism for this. I believe that it is much more universal to disable type-based views. It takes a little to get him attached, but once he is located, the possibilities are endless.

Edit

I do this by associating a RegionName with a property in my ViewModel (maybe GetType (). Name if you want). Then I register the types for the names and it just works.

In the case of something like ListBox, I set the data template:

 <ContentControl Regions:RegionManager.RegionName="{Binding SomeName}" /> 

If you do not want SomeName be on the object to which you are attached, consider a ValueConverter that returns a type name:

 <ContentControl Regions:RegionManager.RegionName="{Binding SomeName, Converter={StaticResource ObjectToTypeConverter}}" /> 

Does it help?

+1
source share

All Articles