Items Control Binding not displaying anything? - wpf

For some reason, my XAML is not displaying anything for my Items Control. I am using a List of Students as my ItemsSource and referencing the properties of that List to create a custom control.
This is my XAML:
<ItemsControl ItemsSource="{Binding Class.Students}" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding FavoriteSubject, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Right now, the drop-down is just empty. The bindings are correct and if I pull them outside the ItemsControl, they display fine. Is there something specific about ItemsControls that I am missing?

Related

WPF TreeView ItemTemplate alighments

i have create my own tree-view with multi column Headers using standard wpf controls
Dock Panel
DataGrid , Just for creating the columns and having sorting and resizing capabilities. The height of datagrid is only 25 , we only need to show columns not data here.
The TreeView Control with hierarchy
i have add the image just to understand the problem and the XAML code
The Account Type should be always align at the left no matter how many levels are expanded in the "first column"
somewhere in the xaml of the TreeViewItemTemplate i lost the idea.. Can anyone help me to fix the alignments
<DockPanel DataContext="{StaticResource cust}">
<Button Command="{Binding rld}" Content="reload" DockPanel.Dock="Top"/>
<!--Unbound DataGrid just to display the headers-->
<DataGrid Height="25" DockPanel.Dock="Top" ItemsSource="{Binding Customers}" AutoGenerateColumns="False" Margin="0,0,0,0">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" x:Name="col0"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding AccountType}" Header="Account Type" x:Name="col1"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<!--Actual Binding with Tree View and item Template to display the properties-->
<TreeView ItemsSource="{Binding Customers}" DockPanel.Dock="Top">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding rel}">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ElementName=col0,Path=ActualWidth}"></ColumnDefinition>
<ColumnDefinition Width="{Binding ElementName=col1,Path=ActualWidth}" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding AccountType}" VerticalAlignment="Center" />
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>
The TreeView naturally indents child items, so its normal what you see.
A possible fix could be to set a negative left margin in the AccountType TextBlock with the same value of the indent, therefore neutralizing the gap.
You need to apply it only if its parent is expanded. This can easily be done modifying a bit your viewmodels.
<TextBlock Grid.Column="1" Margin="{Binding marginPropertyInVM}" Text="{Binding AccountType}" VerticalAlignment="Center"/>
You can limit the size of your first column by changing your template grids column definition to:
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="{Binding ElementName=col1,Path=ActualWidth}" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding AccountType}" VerticalAlignment="Center" />
</Grid>
This way the first column will only be allowed the remaining width once the 2nd column and indent have been allocated their space.

silverlight combobox template binding

I am trying to bind a combobox from a static resource(added on code behind) and add an image beside each item. The best solution I have so far is the following:
<ComboBox x:Name="cmbGroup"
Width="150" Height="32" ItemsSource="{StaticResource Groups}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="Question.jpg" Height="30" MouseEnter="Image_MouseEnter" ></Image>
<ComboBoxItem Content="{Binding Source={StaticResource Groups}}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This is not working, although I can see the image on each item, but instead a text, I got a "Systems.Collection.GenericList". Any ideas how to solve this? Thanks
When you have a control using Binding inside your datatemplate, it is bound to each item in the ItemsSource collection. Also, if you want to display just the string you can use the TextBlock control instead of ComboboxItem. So, if your code looks like:
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="Question.jpg" Height="30" MouseEnter="Image_MouseEnter" ></Image>
<TextBlock Text="{Binding}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I think you will achieve the effect you are looking for.
Hope this helps.
I guess your "Groups" is a a List?
So you configure your template to display an image, and your object Groups by default.
Thus it displays your groups object: ie the toString() of your Groups, which for a List is "Systems.Collection.GenericList".
My guess is that you bind the bad thing? You want to bind an item of your list, which should have a more suitable toString() version.
Let's say you have some Users item in your Groups List. Thus you binding should look like this:
<ComboBox x:Name="cmbGroup"
Width="150" Height="32" ItemsSource="{StaticResource Groups}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="Question.jpg" Height="30" MouseEnter="Image_MouseEnter" ></Image>
<ComboBoxItem Content="{Binding Source={StaticResource Users}}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Hope it helps

How to get selected item value?

How to get ItemsControl display items selected Item textbox text value using MVVM pattern?
<ListBox Margin="0,25,0,0" Grid.Row="3" ItemsSource="{Binding Path=ViewModelSearchResults}" SelectedItem="{Binding Path=SelectedCategoryViewModel, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Path=CategoryName}" FontSize="14" FontWeight="Normal" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=CategoryID}" FontSize="14" FontWeight="Normal" Visibility="Hidden" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
Like getting anything else from Views: bind it! Yes, ItemsControl has SelectedItem but ItemsControl itself doesn't have selection behavior. You should use something like ListBox instead.
You can bind SelectedItem to a property and access the required values through that property.

Binding nested control using MVVM pattern

I have a problem with binding nested control with my MVVM pattern. This is my XAML code:
<ItemsControl Grid.Column="1" ItemsSource="{Binding NotificationContacts}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<toolkit:Expander>
<toolkit:Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ContactName}" Grid.Column="0" VerticalAlignment="Center"></TextBlock>
<Image Source="Images/answer_ok.png" Grid.Column="1" Margin="15,0,15,0" Width="27" Height="27"></Image>
</Grid>
</toolkit:Expander.Header>
<toolkit:Expander.Content>
<ListBox Margin="30,10,0,10" ItemsSource="{Binding NotificationContacts.Messages">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding MessageName}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</toolkit:Expander.Content>
</toolkit:Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The problem is, that the listbox control located in ExpanderControl Data Template is not being data bound.
Listbox control is populated by EntityCollection named 'Messages' which is contained in parent object 'NotificationContacts' that ItemsControl is databound with...
Does anyone know how to resolve this issue ?
Thanks in advance !!!
Did you try this:
<ItemsControl Grid.Column="1" ItemsSource="{Binding NotificationContacts}">
......
<ListBox Margin="30,10,0,10" ItemsSource="{Binding Messages}">
.....
<TextBlock Text="{Binding MessageName}"></TextBlock>
If I remember it right, when you are "inside" ItemContol, binding context is set to NotificationContacts. So use just "{Binding Messages}" could be fine.
And by the way, you are missing curly bracket on the line:
<ListBox Margin="30,10,0,10" ItemsSource="{Binding NotificationContacts.Messages">
Call ItemsControl f.i. "ic" and use next binding in ListBox
<ItemsControl x:Name="ic" Grid.Column="1" ItemsSource="{Binding NotificationContacts}">
...
<ListBox Margin="30,10,0,10" ItemsSource="{Binding ElementName=ic, Path=DataContext.Messages}">

WPF GridViewRowPresenter in an ItemsControl

I'm just starting learning WPF and I'm trying to use a GridViewRowPresenter inside of an ItemsControl to essentially duplicate the functionality of a simple table in HTML. The ListView is not appropriate since it is interactive (which I don't want). I am binding to a generic List of objects of an unknown quantity.
I have a List of a custom object that has two string properties: FirstName and LastName. The following code works:
<ItemsControl Name="myItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=FirstName}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
while this renders nothing:
<ItemsControl Name="myItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<GridViewRowPresenter>
<GridViewRowPresenter.Columns>
<GridViewColumnCollection>
<GridViewColumn DisplayMemberBinding="{Binding Path=FirstName}"></GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=LastName}"></GridViewColumn>
</GridViewColumnCollection>
</GridViewRowPresenter.Columns>
</GridViewRowPresenter>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I'm not sure where to go from here and I would greatly appreciate any help! Thanks!
If you want a non-interactive grid of items, you can use an ItemsControl with a Grid that uses shared size scope:
<ItemsControl ItemsSource="{Binding Items}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="FirstName"/>
<ColumnDefinition Width="*" SharedSizeGroup="LastName"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Grid.Column="1" Text="{Binding LastName}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
A more efficient approach would be to write your own Panel subclass that works similarly to Grid (you could probably subclass Grid) but automatically adds rows as necessary. Then use that Panel as the ItemsPanel for the ItemsControl.

Resources