I want to dynamically load user control to a content control,so i used the "Good Old Method" of changing usercontrol based on DataTemplate.
But on setting the ViewModel property i.e binded to ContentControl content property, ContentControl is displaying "text" conatining the respective viewmodel`s name , instead of loading the respective Usercontrol.
Window`s Resources
<dxr:DXRibbonWindow.Resources>
<DataTemplate x:Key="TYRVM" DataType="{x:Type VM:ProductTYRViewModel}">
<views:TYRUserControl/>
</DataTemplate>
<DataTemplate x:Key="THORVM" DataType="{x:Type VM:ProductTHORViewModel}">
<views:THORUserControl/>
</DataTemplate>
<dxr:DXRibbonWindow.Resources>
Window`s code
<ContentControl Name="content" Content="{Binding Path=VMs,Mode=TwoWay}"/>
Now i don`t know what exactly the problem is!!
You have specified a Key on the DataTemplate so the DataTemplate is not automatically applied based on the Type.
This from MSDN:
This property that is very similar to the TargetType property of the Style class. When you set this property to the data type without specifying an x:Key, the DataTemplate gets applied automatically to data objects of that type. Note that when you do that the x:Key is set implicitly. Therefore, if you assign this DataTemplate an x:Key value, you are overriding the implicit x:Key and the DataTemplate would not be applied automatically.
Link to MSDN : DataTemplate.DataType
Related
For a TextBlock control, I want the Text property to be depending on the current DataContext, and I will display some very nice formatted string-- depending on the type of the DataContext-- with an IValueConverter to properly convert the Text property.
How to do this?
A Binding without a Path (or with Path=.) binds directly to the object in the DataContext of the the TextBlock:
<TextBlock Text="{Binding Converter={StaticResource ...}}" />
I have a WPF UserControl. In the cs part, I have a property of type System.Windows.Data.Binding called ElementBinding.
Here is what the xaml file looks like:
<ItemsControl ItemsSource="{Binding ElementName=ControlRoot, Path=FilteredSource}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ElementBinding, ElementName=ControlRoot}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This doesn't work as intended as it displays (quite logically) the ToString() method of the Binding property.
What I would like to do is appy the Binding property of my UserControl to the Text property of my TextBlock, using the TextBlock DataContext.
I know I can always change my Binding property to a string property and use a converter and reflection to access the path, but I would prefer with a Binding property if it is possible. I guess it is since it's used, for example, in a DataGridColumn.
I'm confused on this for a long time,these both seem to affect the tabitems' presentation in the tabcontrol.
Is it designed for best control of the presentation of the tabcontrol?
Or if there is something I dont't understand.
There's some very long answers here for what is actually a very simple question. To avoid confusion:
ItemTemplate is the template used to format each item in the ItemsSource to create the headers (the controls that appear in the tab bar) and ContentTemplate is the template used to format each item in the ItemsSource to create the content of the tabs (the controls that appear when you click on the header).
The ItemsControl.ItemTemplate Property is used to define what each item in the data bound collection should look like... from the ItemsControl.ItemTemplate Property page on MSDN:
Gets or sets the DataTemplate used to display each item.
As you can see, it is of type DataTemplate, which is customary for a template that displays data... its DataContext will automatically be set to an item from the collection and so controls declared in that DataTemplate will automatically have access to the items properties. Please see the Data Templating Overview page on MSDN for further help with this.
Similarly, from MSDN, the ContentControl.ContentTemplate Property:
Gets or sets the data template used to display the content of the ContentControl.
Again, its DataContext will automatically be set to the object that is set as the Content property. Please note that the ContentControl only has a ContentTemplate Property and no ItemTemplate Property, which is used for collection items... from the Data Templating Overview page on MSDN:
Because myTaskTemplate is a resource, you can now use it on other controls that have a property that takes a DataTemplate type. As shown above, for ItemsControl objects, such as the ListBox, it is the ItemTemplate property. For ContentControl objects, it is the ContentTemplate property.
UPDATE >>>
To clarify this situation further, think of this simple rule:
Use the ContentTemplate property to define how an object that is set as the Content property of a ContentControl should look.
Use the ItemTemplate property to define how the items of a collection control should look.
That the difference at its simplest. However, I'd like to point out that as these properties are both of type DataTemplate, their values are interchangeable.
For example, let's say that you have a Person class and you display a collection of Person objects in a ListBox. You can declare a DataTemplate to set as the ListBox.ItemTemplate property to define how each Person in the collection should look. However, if you just wanted to display a single Person, then you could use a ContentControl with the Content set to an instance of the Person class, and still use the same DataTemplate, but set as the ContentTemplate instead:
Multiple objects:
<ListBox ItemsSource="{Binding People}" ItemTemplate="{StaticResource Template}" ... />
...
Single object:
<ContentControl Content="{Binding Person}"
ContentTemplate="{StaticResource Template}" ... />
Setting the TabControl.ItemTemplate you specify a template to use for all TabItems in the Items collection of the TabControl, unless you override the TabItem.ContentTemplate for a specific TabItem.
So, while they do the same, TabControl.ItemTemplate is a more generic template for all the TabItems in the TabControl and TabItem.ContentTemplate is specific for the TabItem it is used in.
The above is not quite true, as TabControl has an ItemTemplate property and a ContentTemplate property, to make it more confusing.
ItemTemplate is used as template for the header (the tab thingy) of all TabItems added through databinding on the ItemsSource or through Xaml without making the the added item a TabItem:
<TabControl ItemsSource="{Binding ListOfItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Red"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Blue"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
This will create a TabControl with red text in the header/tab and blue text for content.
Now, if we do the following:
<TabControl>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Red"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Foreground="Blue"/>
</DataTemplate>
</TabControl.ContentTemplate>
<TabItem Header="One" Content="One"/>
<TabItem Header="Two" Content="Two"/>
<TabItem Header="Three" Content="Three"/>
</TabControl>
We'll have a TabControl with three tabs, and the header text is black, content is still blue. And a DataError informing us that the ItemTemplate and ItemTemplateSelector properties are ignored for items already of the ItemsControl's container type, in this case TabItem. In this case, we need to specify TabItem.HeaderTemplate to change the appearance of the header.
So TabControl.ItemTemplate and TabItem.ContentTemplate don't do the same, but my previous explanation still holds for TabControl.ContentTemplate and TabItem.ContentTemplate.
I have a ListBox and multiple DataTemplates, in separate files.
<ListBox ItemTemplate="{StaticResource ItemTemplate1}"/>
In the Styles.xaml file:
<DataTemplate x:Key="ItemTemplate1">...</DataTemplate>
<DataTemplate x:Key="ItemTemplate2">...</DataTemplate>
I want to change the ItemTemplate of the ListBox depending on the type of object that's in its list.
Is there a way to access the separate DataTemplates in the code-behind, so that I can bind to a property of my Page?
The way to do that without TemplateSelector is to specify DataType property and don't specify x:Key.
<DataTemplate DataType="{x:Type Type1}">...</DataTemplate>
<DataTemplate DataType="{x:Type Type2}">...</DataTemplate>
In this case appropriate DataTemplate will be automaticly applied in all places where property of specified type have been bound.
But I'd prefer to use TemplateSelector.
To access separated DataTemplate in code-behind you should first get resource dictionary:
var dict = new ResourceDictionary
{Source = new Uri("/ProjectNamespace;component/Styles.xaml", UriKind.Relative)};
Then you can get template:
var dataTemplate = (DataTemplate) dict["ItemTemplate1"];
Try this solution does pretty much what your trying to achieve:
Applying Data Templates Dynamically by Type in WP7
http://www.codeproject.com/Articles/113152/Applying-Data-Templates-Dynamically-by-Type-in-WP7
Its based on WP7 but should work for you too.
There is inbuilt support in WPF for your requirement. Start reading on DataTemplateSelector to select the template at runtime based on certain criteria.
I have an ItemsControl whose ItemsSource gets bound to an ObservableCollection<Component> at run time. I have defined a data template for type Component which works fine.
Now Component has a ObservableCollection<Control> and I want to add another ItemsControl inside my Component Datatemplate to render all the controls. Control here is my own custom object not related to a wpf control.
There are different types of controls so I am trying to use an ItemTemplateSelector to select the right template for each type. In the example below to keep it small I have only shown one of the templates "RWString" which I find using a FindResource in MyControlTemplateSelector overriding SelectTemplate. But the SelectTemplate never gets called(using a breakpoint to check). Is there something wrong in my xaml?
<ItemsControl.Resources>
<src:MyControlTemplateSelector x:Key="XSelector" />
<DataTemplate DataType="{x:Type src:Component}" >
<Expander Visibility="{Binding Path=Show}">
<ItemsControl ItemsSource="{Binding Path=Contrls}"
ItemTemplateSelector="{StaticResource XSelector}">
<ItemsControl.Resources>
<DataTemplate x:Key="RWstring" >
<TextBlock Text="{Binding Path=Label}"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Expander>
</DataTemplate>
</ItemsControl.Resources>
Update: Contrls is not a typo, its just me using a silly naming system. Contrls is a property of Component of type ObservableCollection<Control>. Also the reason I am trying to use the the ItemsTemplateSelector is that the ObservableCollection<Control> contains objects of generic types like Control<int> Control<string> etc all deriving from Control and apparently you cant create datatemplates referring to generic types.
Update3: Removed update 2 as it was unrelated. I got the ItemTemplateSelector to work by changing StaticResource to DynamicResource. But I don't know why this works...
I'm guessing this doesn't work with a StaticResource as the Resource is inside the ItemsControl which probably has not been created at load time when StaticResources are evaluated.
DynamicResources at load time are evaluated to an expression at load time and then evaluated to the correct value when requested.
Try move the Resource outside of the ItemsControl.
In the line where you bind the nested ItemsControl, is the Path correct? It is currently "Contrls", should it be "Controls"?