Display properties of the ListBox.ItemsSource - c#

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>

Related

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

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"/>

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.

Strange artifact when updating Pivot title in Windows Phone 8

I have a XAML page with just a Pivot with binded ItemSource and the following template (changing just the header for simpilcity)
<phone:Pivot
Margin="0,108,0,0"
ItemsSource="{Binding Services}">
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
The ItemSource (Services) is an ObservableCollection of a simple data type with just a Title property implementing INotifyPropertyChanged. When I change the Title of any item, the Pivot header is rendered very strangely:
Here is a complete simplified solution to reproduce the problem: https://dl.dropboxusercontent.com/u/73642/pivotproblem.zip
Is this a Pivot bug?
Indeed a bug... I had the same problem and I end up in forcing to reload whole DataContext of the Pivot.
Since I was using MVVM I just created new instance of the items collection and raised property changed for that.
It seems that TextBlock's Width is not updated after Title changes. You can check it by defining your TextBlock like this:
<TextBlock Text="{Binding Title}" Width="400" />
Hence it's not updated, two Titles overlap each other.

Silverlight - Binding with ObservableCollections

This is no doubt a newbish question, but I have looked for an answer to no avail. My setup is simple: I have a ListBox control defined in XAML and an ObservableCollection<MyClass> in the same class. I am binding the ObservableCollection<MyClass> to the ListBox.
Within the hierarchy of this ListBox in XAML, I want to bind to a given MyClass object, not to a child property of the MyClass object.
To clarify, I have XAML that looks like the following (I bind the ObservableCollection in code):
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<MyControls:SpecialControl MyClassObj="{Binding !!!}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Surely there is a way to get at the object of an ObservableCollection rather than being forced to bind to one of its child properties.
You do not have to specify a Path if you want to use the bound object itself:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<MyControls:SpecialControl MyClassObj="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
BTW: Instead of your custom property, you can use the DataContext property of your control to bind the control to the object:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<MyControls:SpecialControl DataContext="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
As well as specifying the binding path in your XAML you have to bind your collection to the ListBox.
C#
ObservableCollection<MyClass> myCollection = new ObservableCollection<MyClass>();
MyListBox.DataContext = myCollection;
The XAML you have used won't be particularly useful unless you have overriden the ToString method on MyClass. Even though you say you're not are you sure it's not a property of MyClass that you want to bind to? I can't see why you'd want to bind directly to a collection object.
XAML
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<MyControls:SpecialControl MyClassObj="{Binding Path=MyClassProperty}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

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.

Categories