how to dynamically create controls for GridView DataTemplate in WPF? - wpf

I have a GridView control:
<GridView>
<GridViewColumn Header="Name" Width="500">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding TypeName}" Header="Type" Width="100" />
</GridView>
for the first column("name"), I would like to have a mechanism that when every record is binded, will be a way(e.g. event), so that I can dynamically add controls to the StackPanel.
for example, my data has a column called AnimalType, if it is a cat, I will add an image to the StackPanel; if it is a cow, I will put a media element to play a movie; if it is a dog, I will put a hyper link, etc.
How can I do that?

Take a look at the DataTemplateSelector class....
like here:
http://www.wpftutorial.net/DataTemplates.html

Related

ListView style to add ellipsis (...) to all truncated text

I want to create a style for my ListViews in my WPF app, which makes them appear more like the Windows Explorer ListView. The thing I am stuck on is the ellipsis (...) that appears in the Grid/Details view when a column is too narrow to fix the text.
I know I can override the cell template of each column, and explicitly set the TextTrimming mode to get ellipsis on a per-column basis. However, I want a style that I can apply to any ListView to get the same behavior.
I want to be able to define the listview like this:
<ListView ItemsSource="{Binding Library}" Style="{StaticResource ExplorerListStyle}">
<ListView.View>
<GridView>
<GridViewColumn Width="90" Header="Title" DisplayMemberBinding="{Binding Title}" />
<GridViewColumn Width="60" Header="Author" DisplayMemberBinding="{Binding Author}" />
</GridView>
</ListView.View>
</ListView>
I also want to be able to override the cell template for some columns, e.g. to set the text color, ideally while still inheriting the TextTrimming mode for the text in the template.
The only way I have managed to achieve this so far is to explicitly override the TextBlock style inside the ListView:
<ListView ItemsSource="{Binding Library}">
<ListView.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="90" Header="Title" DisplayMemberBinding="{Binding Title}" />
<GridViewColumn Width="60" Header="Author" DisplayMemberBinding="{Binding Author}" />
</GridView>
</ListView.View>
</ListView>
However, this seems a bit heavy handed, and it's not possible, as far as I can tell, to set this in a style.
So, I'm looking for another way to set the TextTrimming mode for a GridViewColumns header and cells, that can be set in a style, and doesn't require explicit CellTemplates.
Thanks,
Mark

How to get selected item of a nested listview?

i have a nested listview, i can bind the selected item of the basic listview to my viewmodel but not my selected item of the nested listview ( in the basic listview ) I just do:
this is my listview:
<ListView Height="155" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="False" Margin="24,506,280,169" Background="#CDC5CBC5"
dd:DragDrop.DropHandler="{Binding}" SelectedItem ="{Binding Path=SelectedCluster,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" ItemsSource="{Binding Path=Clusters,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" >
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Titel" DisplayMemberBinding="{Binding Title}"/>
<GridViewColumn Header="Questions">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ListView DataContext="{Binding}" ItemsSource="{Binding ExaminationQuestions}" SelectedItem="{Binding Path=SelectedExaminationQuestionInCluster,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}">
<ListView.View>
<GridView>
<GridViewColumn Header="Description" DisplayMemberBinding="{Binding Question.Description}"/>
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Viewmodel:
public ExaminationQuestion SelectedExaminationQuestionInCluster
{
get { return selectedExaminationQuestionInCluster; }
set { selectedExaminationQuestionInCluster = value;
OnPropertyChanged("SelectedExaminationQuestionInCluster");
}
}
Someone who knows what i am doing wrong? If i set a breakpoint of the setter of selecteditem of the second listview. He just ignores that..
Thanks
My guess is the binding is probably incorrect. In your outer ListView, you bind to "Clusters". Your inner ListView is probably trying to bind to "SelectedExaminationQuestionInCluster" on the current Cluster. You can see if this is the case by using snoop. It's a valuable tool when debugging WPF apps. It will highlight broken bindings in red and tell you what's wrong with them.
If you want to bind to "SelectedExaminationQuestionInCluster" on the parent DataContext, you could use this syntax:
SelectedItem="{Binding Path=DataContext.SelectedExaminationQuestionInCluster,
ElementName=OuterListView}"
You'll have to give the outer ListView a name of course.
EDIT: I just realized this might not make sense. If each Cluster has its own collection of ExaminationQuestions, then each Cluster should also have a SelectedExaminationQuestion. The parent DataContext should not have any concept of a SelectedQuestion unless it is shared amongst all Clusters.

Custom view listview Binding WPF

Hi I have next XAML markup (just a piece of course):
<Window.Resources>
<GridView x:Key="gridview">
<GridViewColumn Width="200" DisplayMemberBinding="{Binding Title}">
<GridViewColumnHeader Content="Titel" Tag="Title" Click="SortClick"/>
</GridViewColumn>
<GridViewColumn Width="200" DisplayMemberBinding="{Binding Artist}">
<GridViewColumnHeader Content="Artiest" Tag="Artist" Click="SortClick"/>
</GridViewColumn>
<GridViewColumn Width="200" DisplayMemberBinding="{Binding Album}">
<GridViewColumnHeader Content="Album" Tag="Album" Click="SortClick"/>
</GridViewColumn>
<GridViewColumn Width="50" DisplayMemberBinding="{Binding Genre}">
<GridViewColumnHeader Content="Genre" Tag="Genre" Click="SortClick"/>
</GridViewColumn>
<GridViewColumn Width="50" DisplayMemberBinding="{Binding Jaar}">
<GridViewColumnHeader Content="Jaar" Tag="Jaar" Click="SortClick"/>
</GridViewColumn>
</GridView>
<my:IdToImageConverter x:Key="idToImageConverter" />
<DataTemplate x:Key="iconTemplate">
...
</DataTemplate>
<my:PlainView x:Key="iconView"
ItemTemplate="{StaticResource iconTemplate}"
ItemWidth="300"/>
</Window.Resources>
<Grid>
<ListView Name="LibView" ItemsSource="{Binding ElementName=win, Path=Biblio}"/>
</Grid>
Biblio is the observable collection containing the elements for LibView
iconView and gridview are the views i use for LibView. This works perfectly.
Now i want to add a view wich groups every element by "Artist", and i want to display this like:
Artist1 - TitleA - AlbumA
- TitleB - AlbumB
- TitleC - AlbumC
Artist2 - TitleD - AlbumD
...
I guess i have to make some kind of template but i don't even know if this is possible using XAML.
It sound like you want a GroupStyle - this might explain:
http://bea.stollnitz.com/blog/?p=17
There are many examples - try a search on wpf groupstyle :)

Multicolumn listview in WPF at design time

I might sound dumb here, but I want to do something really simple. At design time, I want to add columns to a listview control and add some data to it. I need to add combobox in each column of the listview. The thing I am not able to find is where to mention the column number in the listviewitem. Any help appreciated guys.
<ListView IsSynchronizedWithCurrentItem="True" Margin="8,68,304,188"
BorderThickness="2,2,2,2">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Column1"/>
<GridViewColumn Width="150" Header="Column2"/>
</GridView>
</ListView.View>
<ListViewItem>
</ListViewItem>
</ListView>
Each column in the listviewitem is rendered based on the GridView definition, so there is no real concept of column numbers. What you do is bind objects to the the listview's itemsource and it creates listviewitems from it. Thus, there are a few hoops to jump through.
This link has an example of how to do some simple object data binding. The advantage of this is what binding structure you have for design time can probably be reused for run-time if you set the datacontext/itemsource to an empty object instead of the static one in XAML.
If you're doing this to show examples or you just have a static data source that you want to use, I would recommend using the XmlDataProvider. Then you'd change your ListView to be like this,
<ListView IsSynchronizedWithCurrentItem="True" Margin="8,68,304,188"
BorderThickness="2,2,2,2">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Column1" DisplayMemberPath="{Binding XPath=/A/B}"/>
<GridViewColumn Width="150" Header="Column2" DisplayMemberPath="{Binding XPath=/A/C"/>
</GridView>
</ListView.View>
<ListViewItem>
</ListViewItem>
</ListView>

How can I display different ContextMenus in WPF ListView GridView?

I have a ListView GridView with ListViewItems that represent different categories of items. I'd like to display a different ContextMenu for each category of item. I was hoping to do this using DataTemplates but I'm struggling. My TreeView has a DataTemplate per category and I can see how I can set a different ContextMenu for each there but I can't seem to get similar DataTemplates to work for my ListView. Am I barking up the wrong tree?
E.g. this is one of my DataTemplates for the TreeView:
<DataTemplate DataType="{x:Type viewModel:Cat1ViewModel}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0"
Source="..\Images\cat1.png"/>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
and I can add my ContextMenu to the StackPanel (I hope) and Bob's my uncle.
But the guts of the GridView looks like this:
<ListView.Resources>
<DataTemplate x:Key="image">
<Image Width="16" Height="16" Margin="-3,0,-3,0"
HorizontalAlignment="Center"
Source="{Binding Path=ObjectClass,
Converter={StaticResource imageConverter}}" />
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="20"
CellTemplate="{StaticResource image}"/>
<GridViewColumn Width="140" Header="Name"
DisplayMemberBinding="{Binding Path=Name}"
infrastructure:GridViewSort.PropertyName="Name"/>
<GridViewColumn Width="140" Header="Type"
DisplayMemberBinding="{Binding Path=Category}"
infrastructure:GridViewSort.PropertyName="Category"/>
<GridViewColumn Width="400" Header="Description"
DisplayMemberBinding="{Binding Path=Description}"
infrastructure:GridViewSort.PropertyName="Description"/>
</GridView>
</ListView.View>
This imageConverter in the DataTemplate resource displays the appropriate icon for the category of the listViewItem.
I'm not sure where to start. So, first, is what I want to do possible? If so, can you get me started, please.
Also:
At the moment, each ListViewItem is backed by a viewModel - all categories use the same viewModel class.
Background:
The reason I want to display a different ContextMenu rather than changing the ContextMenu is that I'm using Prism and the ContextMenus will be Regions populated automatically by various modules.
I think you can do this with an ItemTemplateSelector, rather than setting the ItemTemplate property on your ListView, use the ItemTemplateSelector property. You have to create your own implementation of the ItemTemplateSelector class and define the logic so that it knows which template to use for each set of conditions, then you just need to create a set of templates and you should be good to go! There's a good tutorial on how to do this here.

Resources