How to set ItemsSource in XAML? - wpf

I have set ItemsSource of a ListBox as follows :
<ListBox ItemsSource="{Binding abc}" />
What I want
<ListBox>
<listBox.ItemsSource>
?????????????
<listBox.ItemsSource>
</ListBox>

<Window xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ListBox>
<ListBox.ItemsSource>
<x:Array Type="sys:String">
<sys:String>1st item</sys:String>
<sys:String>2nd item</sys:String>
</x:Array>
<ListBox.ItemsSource>
</ListBox>
</Window>

<ListBox>
<listBox.ItemsSource>
<Binding Path = "abs" />
<listBox.ItemsSource>
</ListBox>

Xamarin Example
If you wandered into this page looking for a Xamarin example (the question seems generic to XAML), then you can try -
<Picker x:Name="picker"
Title="Select a monkey"
TitleColor="Red">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
From -
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/picker/populating-itemssource#populating-a-picker-with-data
This uses Picker as an example, but the ItemsSource syntax is interchangeable based on the outer control, like so -
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>mono</x:String>
<x:String>monodroid</x:String>
<x:String>monotouch</x:String>
<x:String>monorail</x:String>
<x:String>monodevelop</x:String>
<x:String>monotone</x:String>
<x:String>monopoly</x:String>
<x:String>monomodal</x:String>
<x:String>mononucleosis</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>

#HighCore, #DanPazey, and #Vishal:
In fact, the markup binding syntax may prove to be useful and even necessary.
Not to mention multibinding, consider the following.
Suppose you need to bind your ListBox to CollectionViewSource (for sorting or else). Like this:
<Window.Resources>
<CollectionViewSource x:Key="abc_CVS_Key" Source="{Binding abc}" />
</Window.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource abc_CVS_Key}}">
</ListBox>
You may want then, for technical reasons, to limit a scope of the CVS resource to only the ListBox in question.
If you write down ItemsSource binding in an attribute
<ListBox ItemsSource="{Binding Source={StaticResource abc_CVS_Key}}">
<ListBox.Resources>
<CollectionViewSource x:Key="abc_CVS_Key" Source="{Binding abc}" />
</List.Resources>
</ListBox>
your code will compile, but runtime your program will not find your abc_CVS_Key resource key, because the resource has been defined later in code. You need to define the resource before you refer to it in ListBox' ItemsSource binding. Like this:
<ListBox>
<ListBox.Resources>
<CollectionViewSource x:Key="abc_CVS_Key" Source="{Binding abc}" />
</List.Resources>
<ListBox.ItemsSource>
<Binding Source="{StaticResource abc_CVS_Key}" />
</ListBox.ItemsSource>
</ListBox>
This code compiles and executes OK.

Related

Nested Datagrid in ListBox

I have a datagrid nested inside the ItemTemplate of a ListBox. I'm trying to display a tree like data structure using this. My classes are as follows.
The object in my data context contains a List<Section> named Sections, my ListBox is bound to this. Each Section contains a List<Item> named Items, the DataGrid in eac ItemTemplate is bound to this.
When I run the app, I get a null reference exception from the XAML at the line with the binding. Is there a better/alternative way of doing this, or am I missing a trick with the binding?
<Window.Resources>
<CollectionViewSource x:Key="SectionSource" /><!-- this is initialized and filled with an ObservableCollection<Section> Sections when the window loads-->
</Window.Resources>
<ListBox x:Name="lstIngredients" ItemsSource="{Binding Source={StaticResource SectionSource}}">
<ListBox.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<CollectionViewSource x:Key="itemsSource" Source="{Binding Items}"/>
</DataTemplate.Resources>
<DataGrid x:Name="dgItems" IsReadOnly="false" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="FullRow" IsSynchronizedWithCurrentItem="True"
DataContext="{Binding}"
ItemsSource="{Binding Source={StaticResource Items}}"
EnableRowVirtualization="false"
VirtualizingStackPanel.VirtualizationMode="Standard"
<DataGrid.Columns>
<DataGridTemplateColumn Width="2*" Header="{lex:LocText ChickenPing.Shared:Strings:Measurement}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="quantity" Text="{Binding Measurement}" TextTrimming="CharacterEllipsis" TextAlignment="Left"/>
<!-- Null reference on this line caused by the binding. If I set this to any DependencyProperty on an Item object, I get a null reference-->
</DataTemplate>
This need to be path
ItemsSource="{Binding Source={StaticResource Items}}"
ItemsSource="{Binding Path=PropertyThatIsCollection}"
And delete the DataContext line
I eventually tracked this down to an event which was set in one of the TemplateColumns. Switching the event from
<TextBlock x:Name="quantity" Text="{Binding Measurement}" GotFocus="txt_GotFocus" />
to
<Style x:Key="FocusableTextbox" TargetType="{x:Type TextBox}">
<EventSetter Event="GotFocus" Handler="txt_GotFocus" />
</Style>
...
<TextBlock x:Name="quantity" Text="{Binding Measurement}" Style={StaticResource FocusableTextbox} />

WPF UserControl or ControlTemplate... (not sure)

I have a listbox where I have to add about 20 static custom items. All the items are based on the same template (something like that) :
<Border>
<StackPanel Orientation="Horizontal">
<Image Source="" Height="30" />
<TextBlock Text="" VerticalAlignment="Center" />
</StackPanel>
</Border>
I don't want to repeat that 20 times in the ListBox.Items I would like to have some kind of UserControl where I could do something Like the following where I could set some custom properties :
<ListBox>
<ListBox.Items>
<MyListBoxTemplate x:Name="Item1" ItemText="Item #1" ItemImageSource="/Image1.jpg" />
<MyListBoxTemplate x:Name="Item2" ItemText="Item #2" ItemImageSource="/Image2.jpg" />
...
</ListBox.Items>
</ListBox>
But I don't wan't to create a userControl just for that!!! Is there an easy way to put that template in the Window.Resources?
Thanks
If you are ONLY using it for that SPECIFIC listbox, you can just assign the ItemTemplate property. This will need to work in conjunction with a collection of custom objects defined in your resources somewhere else. This will save you from creating a custom UserControl, but you will need an object that can be defined in XAML and a list of them in XAML anyway. To be honest, creating a UserControl is relatively painless and may be easier, but it is possible without doing so.
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate TargetType="CustomObjectType">
<Border>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageSource}" Height="30" />
<TextBlock Text="{Binding TextContent}" VerticalAlignment="Center" />
</StackPanel>
</Border>
<DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EDIT: If you are going to use it in more than one place, put the DataTemplate in your Application resources and ive it a key, then assign the ItemTemplate property to {StaticResource MyListBoxItemsTemplateKey}
Not my favorite approach since it uses the XmlDataProvider and XPath syntax (which I tend to always forget). But you can embed your static data as xml within your Window.Resources like so:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<XmlDataProvider x:Key="MyStaticData" XPath="StaticItems" >
<x:XData>
<StaticItems xmlns="">
<StaticItem>
<ItemText>Item #1</ItemText>
<ItemImageSource>/Image1.jpg</ItemImageSource>
</StaticItem>
<StaticItem>
<ItemText>Item #2</ItemText>
<ItemImageSource>/Image2.jpg</ItemImageSource>
</StaticItem>
</StaticItems>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<Grid>
<ListBox>
<ListBox.ItemsSource>
<Binding Source="{StaticResource MyStaticData}" XPath="StaticItem" />
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding XPath=ItemImageSource}" Height="30" />
<TextBlock Text="{Binding XPath=ItemText}" VerticalAlignment="Center" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Then within your ListBox bind to the XmlDataProvider you specified and use the XPath notation within the bindings to drill down to the data you want the controls to bind to.
This site has a couple good examples too:
http://vbcity.com/blogs/xtab/archive/2010/12/24/more-xpath-examples-in-a-wpf-application.aspx
Hope this helps!

XAML array issue

I am using the following arrays as parameters to my value converter. I can't figure why "params2" is passed as an ArrayExtension and "params1" is passed as a simple TextBlock[] array.
<Window.Resources>
<x:Array Type="TextBlock" x:Key="params1">
<TextBlock Text="{x:Static local:Constants.MyDir}"></TextBlock>
<TextBlock>25</TextBlock>
</x:Array>
</Window.Resources>
<TabItem.Resources>
<x:Array Type="TextBlock" x:Key="params2">
<TextBlock Text="{x:Static local:Constants.MyDir}"></TextBlock>
<TextBlock>55</TextBlock>
</x:Array>
</TabItem.Resources>
Image Viewer XAML:
<Window x:Class="TotalViewer.ImageViewerWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TotalViewer"
Title="ImageViewerWindow" Name="ImageViewerWindow1">
<Window.Resources>
<x:Array Type="TextBlock" x:Key="params1">
<TextBlock Text="{x:Static local:Constants.MyDir}"></TextBlock>
<TextBlock>25</TextBlock>
</x:Array>
</Window.Resources>
<Grid>
<Image Source="{Binding ElementName=ImageViewerWindow1, Path=ImagePath,
Converter={StaticResource ImageConverter},
ConverterParameter={StaticResource params1}}"/>
</Grid>
</Window>
Well, I kinda gave up for the moment because I need to get this part working. In the converter, I test if the parameter is either ArrayExtension or TextBlock[]. If it's ArrayExtension, it will get converted to TextBlock[].

How can I bind and sort a collection

If I have an unsorted collection, is there an easy way to bind and sort it. I would like to do it in XAML (no Linq, no C#)
If my DataContext has a property, say, MyItems, it is easy to bind against it:
<ListBox ItemsSource={Binding MyItems}/>
However, I'd like to sort it as well. Using the CollectionViewSource should be the solution but it does not work for me:
<ListBox>
<ListBox.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source={Binding MyItems}/>
</Binding.Source>
</Binding>
</ListBox.ItemsSource>
</ListBox>
At this point, my ListBox loses its elements.
Am I missing something obvious?
You can define the CollectionViewSource as a resource and provide your desired sorting...
<Window.Resources>
<CollectionViewSource x:Key="cvs" Source="{Binding MyItems}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="MyItemName" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Source={StaticResource cvs}}"/>
</Grid>
The scm namespace is xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Create a CollectionViewSource in the CodeBehind which reads from MyItems, and bind your ListBox to that
<ListBox ItemsSource="{Binding MyCollectionViewSource"} />
Neither of the other answers actually address sorting. They are both right about a CollectionViewSource, but you can use that to do the sorting, with CollectionViewSource.SortDescription. Taken from here and modified:
<Window.Resources>
<src:MyItems x:Key="MyItems"/>
<CollectionViewSource Source="{StaticResource MyItems}" x:Key="cvs">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="CityName"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource cvs}}"
DisplayMemberPath="CityName" Name="lb">
<ListBox.GroupStyle>
<x:Static Member="GroupStyle.Default"/>
</ListBox.GroupStyle>
</ListBox>
In this example,CityName would be the property on each item in MyItems used to do the sorting

How to properly bind a ListBoxItem in WPF?

I have a listbox and I want to iterate over a collection of Bars in my Foo-object.
<ListBox DataContext="{Binding Path=Foo.Bars}" >
<ListBox.Items>
<ListBoxItem>
<ContentControl DataContext="{Binding Path=.}" />
</ListBoxItem>
</ListBox.Items>
</ListBox>
This is the datatemplate I want to use.
<DataTemplate DataType="{x:Type Bar}">
<Label Content="hello stackoverflow" />
</DataTemplate>
If I snoop (--> examine by using the tool Snoop) my application, I notice that the entire collection of Bars is bound to the ContentControl, in stead of just 1.
How can I properly bind so the iteration over the collection goes fine?
You can just set the DataTemplate, and WPF does all the work. Set the ItemsSource to a list of Bar items, and then define a DataTemplate for Bar items.
<ListBox ItemsSource="{Binding Path=Foo.Bars}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type Bar}">
<Label Content="hello stackoverflow" />
</DataTemplate>
</ListBox.Resources>
</ListBox>
You could also set the ItemsTemplate directly by using <ListBox.ItemTemplate> instead of <ListBox.Resources>
See Data Binding Overview at MSDN.
First add your namespace to the Window element (Intellisense) :
xmlns:local="clr-namespace:yourenamespace"
Then the following XAML ( in Window.Resources is a clean way to do it ) :
<Window.Resources>
<ObjectDataProvider x:Key="DataProvider" ObjectType="{x:Type local:Foo}"/>
<DataTemplate x:Key="Template" >
<TextBlock Text="{Binding Bar}"/>
</DataTemplate>
</Window.Resources>
Place the Listbox :
<ListBox DataContext="{Binding Source={StaticResource DataProvider}}" ItemsSource="{Binding Bars}" ItemTemplate="DynamicResource Template" />
But, it depends on your code-behind object, you have to set a constructor to initialise public properties within your object which are ObservableCollection<> preferably (There is some restriction rules with object instance in XAML).

Resources