3

I have a Listbox inside a UserControl to manage different entities with different properties. The UserControl is the same for all entities. I use MVVM and i bind a generic ViewModel as DataContext for the UserControl. I wish to set the ItemTemplate for the Listbox in the container xaml for the UserControl in order to display the entity properties. For the entity "Emlployee" I need to display FullName, for the entity Certifying I need to display CertifyingAuthor and CertifyingDate and so on.

What I need is something similar to that

 <StackPanel Grid.Row="0" Orientation="Vertical"> <uc:SearchableFromListTextBox ItemTemplateForTheInsideListBox="{StaticResource Something}" ></uc:SearchableFromListTextBox> 

Should I add a dependencyProperty ItemTemplateForTheInsideListBoxProperty to the UserControl? And how i could pass it as itemtemplate of the Listbox?

Hope the question is well explained considering my italian native language. thanks

EDIT : I give up. This is a control for keyboard data entry and something similar to autocomplete. Since i am forced to agree to a compromise with MVVM :( i will choose some dirty way to resolve. Thanks to all

4
  • you really should use typed viewmodels instead of a generic. It makes life much more easy. stackoverflow.com/questions/19864891/… Commented Nov 4, 2016 at 15:43
  • you can also use a template selector. But I still suggest you make different ViewModels and work with the DataTemplate.TargetTypemsdn.microsoft.com/en-us/library/… Commented Nov 4, 2016 at 15:45
  • It seems that using DataTemplates result in design the whole usercontrol. I wish the rest of controls to remain the same. the only difference is on the itemtemplate of the listbox control Commented Nov 4, 2016 at 16:03
  • I might suggest dependency injection using an interface where your items control template binds to the data context's collection of interfaces. Commented Nov 4, 2016 at 19:08

1 Answer 1

0

A DataTemplateSelector can do what I think you want. You can define different templates from your user control's XAML, then have the selector choose among them.

Assume these model classes:

public class Employee { public Employee(string fullName) { FullName = fullName; } public string FullName { get; } } public class Certifying { public Certifying(string certifyingAuthor, DateTime certifyingDate) { CertifyingAuthor = certifyingAuthor; CertifyingDate = certifyingDate; } public string CertifyingAuthor { get; } public DateTime CertifyingDate { get; } } 

Your user control's XAML has a ListBox, which in turn uses a template selector (that we'll get to in a moment) -- and also defines different templates for the two different model types:

<UserControl x:Class="WPF.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WPF" > <Grid> <ListBox x:Name="listBox"> <ListBox.ItemTemplateSelector> <local:MyTemplateSelector> <local:MyTemplateSelector.EmployeeTemplate> <DataTemplate DataType="local:Employee"> <TextBlock Foreground="Red" Text="{Binding FullName}" /> </DataTemplate> </local:MyTemplateSelector.EmployeeTemplate> <local:MyTemplateSelector.CertifyingTemplate> <DataTemplate DataType="local:Certifying"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="120" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Foreground="Blue" Text="{Binding CertifyingAuthor}" /> <TextBlock Grid.Column="1" Foreground="Green" Text="{Binding CertifyingDate}" /> </Grid> </DataTemplate> </local:MyTemplateSelector.CertifyingTemplate> </local:MyTemplateSelector> </ListBox.ItemTemplateSelector> </ListBox> </Grid> </UserControl> 

The user control's code-behind, where I just assign a list of model objects to the list box (for simplicity):

public partial class UserControl1 { public UserControl1() { InitializeComponent(); listBox.ItemsSource = new List<object> { new Employee("Donald Duck"), new Certifying("Mickey Mouse", DateTime.Now), new Employee("Napoleon Bonaparte"), new Certifying("Homer Simpson", DateTime.Now - TimeSpan.FromDays(2)), }; } } 

And finally, the template selector. Its two properties were set from the user control's XAML; the logic of SelectTemplate decides which one to apply:

public class MyTemplateSelector : DataTemplateSelector { /// <summary> /// This property is set from XAML. /// </summary> public DataTemplate EmployeeTemplate { get; set; } /// <summary> /// This property is set from XAML. /// </summary> public DataTemplate CertifyingTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { if (item is Employee) { return EmployeeTemplate; } if (item is Certifying) { return CertifyingTemplate; } return base.SelectTemplate(item, container); } } 

And, for completeness, usage of the user control:

<Grid> <wpf:UserControl1 /> </Grid> 

The end result, where Napoleon is currently selected, and Homer suffers a mouse-over:

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

thanks peter for you answer. The fact is your solution needs the usercontrol to be implemented each time new object type comes out. On the other hand i believe the template selector can be moved to a resource dictionary avoiding usercontrol implementation. So i guess i can mark as answer. Thanks again An thanks to @Mat who gave probably same answer but i guess i didn't understand correctly
Replace first "guess" with "Think" and the second one with "Believe". i checked the meaning on wordreference.com :) (hoping it's correct now)
Yes, you can certainly move the template selector to a resource dictionary. I would. :-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.