I have a listview with a ItemTemplateSelector to load my custom datatemplate based on a model. I'd like to know if i can use another TemplateSelector inside the main DataTemplate to load another Datatemplate to change the listview item DataTemplate based on the same model.
Main ListView
<ListView
Padding="10"
Grid.Row="1"
ItemsSource="{Binding DbObjectList, Mode=TwoWay}"
IsItemClickEnabled="True"
ItemTemplateSelector="{StaticResource TemplateSelector}"
x:Name="Comps">
Main DataTemplate
<DataTemplate x:Key="SetupDataTemplate" x:DataType="data:Setup">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{x:Bind text}" HorizontalAlignment="Stretch" FontSize="16" />
<ContentControl Grid.Column="1" Content="{Binding}" ContentTemplateSelector="{StaticResource SetupTemplateSelector}" />
<TextBlock Grid.Column="2" Text="{x:Bind key}" HorizontalAlignment="Stretch" FontSize="16" />
</Grid>
</DataTemplate>
I tried to use ContentControl/ContentPresenter to load the DataTemplate i want, but the Content property is always NULL.
<ContentControl Grid.Column="1" Content="{Binding}" ContentTemplateSelector="{StaticResource SetupTemplateSelector}" />
SetupTemplateSelector
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
.....
}
I need to pass the Listview item to SetupTemplateSelector to choose my DataTemplate.
Is it the right way to do that?
Are there better solutions to solve my problem?
If you need more just ask!
Thanks
Related
I have the following DataTemplate where inside is a Grid with a 'TextBlock' and TextBox that I want to align to the center:
<DataTemplate x:Key="OneSettingsEntryTemplate" DataType="{x:Type templateHelper:InputText}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Style="{StaticResource StandardTextBlocksStyle}"
Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Column="1"
Style="{StaticResource DefaultTextBoxesStyle}"
Text="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
In one of my UserControls I have the following code where I use the Template:
<StackPanel DataContext="{Binding ElementName=ControlForProjectSettings, Path=ViewModel}"
HorizontalAlignment="Center">
<TextBlock Style="{StaticResource HeadingTextBlocksStyle}"
Text="Project settings"/>
<ListView Background="#DAE7F5"
ItemsSource="{Binding ProjectSettingEntries}"
ItemTemplate="{StaticResource OneSettingsEntryTemplate}">
</ListView>
</StackPanel>
When I run my application and display some items, the last item has a longer text and therefore the TextBox flips to the right. Application Image
I tried playing around with the HorizontalAlignment and VerticalAlignment properties inside the Grid or also using a DockPanel instead of a Grid but couldn't find a solution. Any ideas?
Thanks to this source: WPF share column width between separate grids I solved my problem.
I added the IsSharedSizeScope to my Grid and the SharedSizeGroup property to my columns.
<Grid IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
</Grid.ColumnDefinitions>
So, i have the following xaml at the moment-
<Window.Resources>
<DataTemplate x:Key="MailTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Date}" Width="150"/>
<TextBlock Text="{Binding Path=Subject}" Width="300"/>
<TextBlock Text="{Binding Path=From.DisplayName}" Width="125"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
It's a template of a ListBox item.
The actual details do not really matter, its just about the Width attribute.
Is there a way to access the window's size in order to set the width? I don't want the Width to be constant, i want the TextBlocks to be able to change sizes if you stretch the window.
You can do that by not setting any fixed widths on the TextBlock elements, and use a Grid with star-sizing instead of a StackPanel as container. For example like this:
<DataTemplate x:Key="MailTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150*" />
<ColumnDefinition Width="300*" />
<ColumnDefinition Width="125*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Date}" />
<TextBlock Grid.Column="1" Text="{Binding Path=Subject}" />
<TextBlock Grid.Column="2" Text="{Binding Path=From.DisplayName}" />
</Grid>
</DataTemplate>
My Code looks like this:
<ItemsControl ItemsSource="{Binding Path=MTMngRoot.MTManager.MTCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Path=Name}" ToolTip="Name" Controls:TextBoxHelper.Watermark="Name" Grid.Column="0"/>
<ComboBox SelectedItem="{Binding Path=DefaultCT}" Grid.Column="1">
<ComboBoxItem>Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
</ComboBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This code works correctly. But now I want to bind the Itemssource from the ComboBox. My Problem is now, the Path of the Items that should be bind to the ComboBox is completly different. The Path looks like this: CTMngRoot.CTManager.CTCollection.Name. Any ideas how I can do this?
You walk up to the control with the correct DataContext in these cases.
{Binding DataContext.CTMngRoot.CTManager.CTCollection,
RelativeSource={RelativeSource AncestorType=ItemsControl}}
I have a data template like this
public class DefaultDataTemplate : DataTemplate
{
public string Name
{
get;
set;
}
}
and I am using in xaml like this
<!-- Default DataTemplate -->
<DataTemplate x:Key="DefaultDataTemplate">
<Grid Margin="4" MinHeight="25">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
</Grid>
</DataTemplate>
I want to do binding with the "Name" Property of my datatemplate ,but right now its binded to my List view item's property named "Name".Can anybody help for the correct way or syntax
The DataContext for a DataTemplate is the DataObject it is templating, you will have to bind back to the DataTemplate or in this case DefaultDataTemplate to access the property.
Try:
Text="{Binding Name, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataTemplate}}}
or
Text="{Binding Name, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type myNamespace:DefaultDataTemplate }}}
You are not using the template, you just gave the template the same key name as the class.
Also, the custom data template should have dependency properties to bind to.
Do you actually mean to do this:
<ListBox ItemsSource="{Binding Persons}">
<ListBox.DataTemplate>
<DataTemplate >
<Grid Margin="4" MinHeight="25">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="Name" FontWeight="Bold" />
<TextBox Margin="8,0" Grid.Column="1" Text="{Binding Name}" />
</Grid>
</DataTemplate>
</ListBox.DataTemplate>
</ListBox>
Or perhaps
<Window.Resources>
<DataTemplate x:Key="DefaultDataTemplate">
<Grid Margin="4" MinHeight="25">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="Name" FontWeight="Bold" />
<TextBox Margin="8,0" Grid.Column="1" Text="{Binding Name}" />
</Grid>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding Persons}" DataTemplate="{StaticResource DefaultDataTemplate}"/>
Assuming the Person class has a property Name and the Persons property is an Observable<Person>
I have a list view that is binded to some object I've created.
The binding is working perfect, but I want to add icon to each item in my list.
All the items should have the SAME icon (should be defined prior as "file.ico").
What is the best to implement this?
Thanks.
Use an ItemTemplate, e.g:
<ListBox ItemsSource="{Binding MyItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="/Images/.." Width=".." Height=".." />
<TextBlock Grid.Column="1" Text="{Binding Name}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You should use a ListBox unless you have a specific reason to use a ListView.