Using ItemTemplate and DataTemplate creates a button within ListView. Why? - c#

I have a situation with a ListView. Inside the item template there is a DataTemplate and inside the DataTemplate there is a ListViewItem and it's content is bound. When I click I want to select the item but when I hover my mouse over it, it seems like there is a button created with the ItemTemplate and DataTemplate . At the moment, I can select item by clicking somewhere else within the same row, but that doesn't work if I select the button. I use SelectedItem and if you click on the button within the item, the SelectedItem will not fired.
The ListView is linked to an ItemSource, and SelectedItem of the ListView is bound to a property
Further information: language is C#, ide is Visual Studio 2010.
I will leave my xaml code below, Thanks.
XAML
<ListView x:Name="myListView"
Grid.Column="0"
Grid.Row="2"
Height="Auto"
Margin="0,0,0,0"
SelectionChanged="SchemaListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem Content="{Binding Path=Value}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#
void ReadData(string id)
{
var data = ExampleData.GetData(id);
myListView.ItemsSource = data.Results;
}
I've tried binding without ItemTemplate and DataTemplate also tried to link source in xaml but that didn't work

You must not have a ListViewItem in the ItemTemplate of a ListView.
When the elements of the ItemsSource collection are not already ListViewItems (which they typically never are), the framework will automatically create a ListViewItem that becomes the "item container" element for each data item. This automatically generated ListViewItem uses the ItemTemplate as its ContentTemplate.
Besides that, use a ListBox instead of ListView when you do not set a ListView's View property.
So instead of a ListViewItem, use a ContentControl or perhaps a TextBlock:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If there is nothing more than a single content element, simply set the DisplayMemberPath property:
<ListBox ... DisplayMemberPath="Value"/>

Related

How can I reference the ListView DataContext from within the ListView.ItemTemplate in XAML?

I have a ListView whose DataContext is set to my ViewModel. The ListView.ItemsSource is set to a Collection Property of the ViewModel. There is a Property called MyIndex say on this ViewModel. The value of MyIndex changes during the execution of my project.
I need a way to access in XAML 'MyIndex' from within the ItemTemplate of the ListView so that I can change aspects of each ListViewItem based on the value of MyIndex.
I can't use TemplatedParent and then the .Parent property of the ListViewItem in the binding as .Parent isn't the ListView.
Here is some pseudo XAML to illustrate better what I mean.
<ListView ItemsSource="ItemsCollection">
<ListView.ItemTemplate>
<ItemContainerTemplate>
<Grid Background="{Binding <some xaml to reference MyIndex Property of ListView.DataContext to use in Converter>}">
</Grid>
</ItemContainerTemplate>
</ListView.ItemTemplate>
</ListView>
I'm not experienced with WPF.
This should do the trick. That way, you can use the DataContext of the parent in the children.
<ListView ItemsSource="ItemsCollection">
<ListView.ItemTemplate>
<ItemContainerTemplate>
<Grid Background="{Binding DataContext.MyIndex, RelativeSource={RelativeSource AncestorType=ListView}}">
</Grid>
</ItemContainerTemplate>
</ListView.ItemTemplate>
</ListView>

Hide last item in a ItemsControl

I've a ItemsControl that I bind to my viewmodel, but inside the datatemplate I also have an image. I want that image to be visible as long as it's not the last item in the list, then it should be hidden (it's an arrow that point down to the next control).
The xaml look like this:
<ItemsControl ItemsSource="{Binding PageContainers}" x:Name="Items">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<controls:DesignControl DataContext="{Binding}" MouseDown="UIElement_OnMouseDown" MouseUp="UIElement_OnMouseUp" MouseMove="UIElement_OnMouseMove"/>
<Image Source="/Resources/Images/arrow.png" Height="16" Width="16" Margin="0,10,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
So is there any easy to check if the Image/Stackpanel is last in the list? I guess I could subscribe to some event and do it in the code behind, but I guess it's cleaner if I could do it inside the xaml.
You're binding to PageContainers which I assume to be a collection. Can the type of that collection be extended to include an IsLast property?
If it can, you can bind the visibility to that.

How to access an item in a DataTemplate?

I defined a ListView like this:
<ListView x:Name="libraryBooksListView"
AutomationProperties.AutomationId="VideoListView"
AutomationProperties.Name="Videos"
TabIndex="1"
Padding="0,0,4,0"
ItemsSource="{Binding}"
IsSwipeEnabled="False"
ItemTemplate="{StaticResource LibraryBooksItemTemplate}"
ItemContainerStyle="{StaticResource LibraryListViewItemStyle}"
Grid.Column="1"
SelectionMode="None">
</ListView>
and I defined the LibraryBooksItemTemplate like this:
<DataTemplate x:Key="LibraryBooksItemTemplate">
<Grid Margin="0">
<GridView x:Name="booksGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
ItemsSource="{Binding Items}"
ItemTemplateSelector="{StaticResource textbookTemplateSelector}"
SelectionMode="Multiple"
IsItemClickEnabled="True"
ItemClick="booksGridView_ItemClick"
SelectionChanged="booksGridView_SelectionChanged"
IsSwipeEnabled="false"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</DataTemplate>
The GridView, booksGridView, has multiple items (books).
How to modify/access the "ItemTemplateSelector" and SelectionMode etc. of the GridView?
Is there a way to access each of the items in the booksGridView?
Thx
There are many ways to do that.
The easiest one is to wrap your DataTemplate contents into a UserControl.
Another one is to use something like ContainerFromIndex().
Then you can also use VisualTreeHelper class to walk the visual tree.
Then again you can subclass your ItemsControl and override GetContainerForItemOverride() or
PrepareContainerForItemOverride() or
use the ItemContainerGenerator property
The imporant thing to note is that your ItemsSource provides items to the control while the overrides or the generator provide containers to display the items using the ItemTemplates.
*Edit As for your additional questions:
How to modify/access the "ItemTemplateSelector" and SelectionMode etc. of the GridView?
You have defined your selector resource and gave it a key of "textbookTemplateSelector", so you can just get it with this.Resources["textbookTemplateSelector"]. SelectionMode you can bind to the same source DataContext you bound your ItemsSource to and change or read it through a binding.
Is there a way to access each of the items in the booksGridView?
Yes. Since your DataContext is set as the ItemsSource of your ListView - you can access all the items through that DataContext. Each of these items seems to have an Items property that is bound to your GridView, so you can access each of these through the Items property you have defined yourself.
You can access it by using ItemsSource:
foreach(var book in this.booksGridView.ItemsSource)
{
}

Display custom object data to ListBox WPF

I have a ListBox in WPF application as :
<ListBox HorizontalAlignment="Left" Margin="16,37,0,16" Name="lbEmpList" Width="194" SelectionChanged="lbEmpList_SelectionChanged" FontSize="12" SelectionMode="Single">
</ListBox>
I have three buttons: Add, Remove and Update that will add, remove and update items to the list box. I am adding Items to the ListBox my custom class object names objEmployee.
This custom class contains few properties: Id, Name, Address.
But, when I add the object to ListBox, then it will display items as
<Namespace Name>.<Custom Object name>
How can I bind any of the object property to this ListBox at Design or run time to acheive my functionality?
Couple of options:
The first, easiest option is to set the ListBox's DisplayMemberPath property to a property of your custom object. So if your Employee class has a LastName property you could do this:
<ListBox DisplayMemberPath="LastName" ... />
If you want more control over the data that's displayed for each item (including custom layout etc) then you'll want to define a DataTemplate for each item in your ListBox. The easiest way to do this is by simply setting the ListBox's ItemTemplate property:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Have a read through the links I've provided and check out some of the example code on MSDN.

Display properties of the ListBox.ItemsSource

I am new to WPF. I have a ListBox that has its ItemSource set to a instance of WorkItemCollection. (A collection of WorkItem objects.)
When the list is displayed it only displays the type of each object (Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem). Is there a way to make the list display WorkItem.Title?
You have two options.
The simplest method is to set the DisplayMemberPath property of your ListBox to "Title".
If you want to set not only what gets displayed, but the type of control that is used to display it, then you would set the ListBox's ItemTemplate.
For what your goal is, I would recommend the first option.
You can set a DataTemplate on the ItemTemplate property of the ListBox:
<ListBox ItemSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate DataType="tfs:WorkItem">
<StackPanel>
<TextBlock Text="{Binding Title}" />
<!-- Others -->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Categories