Reputation: 153
I suspect the answer to my problem is pretty simple but I have had a good look around the forum and can't seem to find anything quite the same.
I have a reasonably complex binding structure with a ItemsControl at the far end but it only shows the first item. I can see the data on the code side is correct and holds only 8 items, the first item is displayed correctly with all labeling and colours as required.
The logic side structure is like:
The XAML structure is like:
Here's a simplified version of the code:
Items control and its data template inside the GroupBox ControlTemplate whose datacontext is an instance of WaterSampler.
<ControlTemplate x:Key="WaterSamplerGroupBoxTemplate" TargetType="{x:Type GroupBox}" >
<GroupBox Header="{Binding Path=Header}" Width="300" Margin="10,5,10,0" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<DataTemplate x:Key="BottleStateDataTemplate">
<Button Template="{DynamicResource ValveStatusTemplate}" />
</DataTemplate>
</StackPanel.Resources>
<ItemsControl Name="bottleStateListBox" ItemTemplate="{StaticResource BottleStateDataTemplate}" Margin="5" Height="50" ItemsSource="{Binding BottleIsFullList}" DataContext="{Binding Parameters}"/>
</StackPanel>
</GroupBox>
</ControlTemplate>
The simplified button control template:
<ControlTemplate x:Key="ValveStatusTemplate" TargetType="{x:Type Button}" >
<StackPanel Orientation="Vertical" Width="30" Margin="5" >
<TextBlock Text="{Binding Number}" FontSize="18" Canvas.Left="8"/>
</StackPanel>
</ControlTemplate>
The class that holds the data for the item template:
public class DisplayBottleStateClass : INotifyPropertyChanged
{
private int number;
public int Number
{
get { return number; }
}
}
The class containing the list of DisplayBottleClass:
public class WSParametersClass : INotifyPropertyChanged
{
private List<DisplayBottleStateClass> bottleIsFullList = new List<DisplayBottleStateClass>();
public List<DisplayBottleStateClass> BottleIsFullList
{
get { return bottleIsFullList; }
}
}
The class containing the parameters class:
public class WaterSampler : INotifyPropertyChanged
{
private WSParametersClass parameters = new WSParametersClass();
public WSParametersClass Parameters
{
get { return parameters; }
set { parameters = value; OnPropertyChanged("Parameters"); }
}
}
Finally the MainWindow class:
public partial class MainWindow : Window
{
public class WaterSamplerListClass : ObservableCollection<WaterSampler> { }
private WaterSamplerListClass waterSamplers = new WaterSamplerListClass();
public MainWindow()
{
waterSamplers.Add(new WaterSampler(0));
WaterSampler0Group.DataContext = (waterSamplers[0]);
}
}
I do get a binding error for the two brushes that I use but when I replace these with fixed values in the XAML still only the first element is displayed. The list also seems to update correctly through the binding as I can see the first element changing correctly. The error I get is:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=GradientStopHighlight; DataItem=null; target element is 'GradientStop' (HashCode=23577486); target property is 'Color' (type 'Color')
Any suggestions would be very welcome.
Thanks very much
Ed
Upvotes: 0
Views: 2740
Reputation: 39261
Try set the CacheLength
property on the ItemsPanelTemplate.ItemsStackPanel
of your ItemsControl
.
CacheLength
as defined by MSDN:
The size of the buffers for items outside the viewport, in multiples of the viewport size. The default is 4.0.
Remarks
To improve scrolling performance, ItemsStackPanel creates and caches item containers for items that are off-screen on both sides of the viewport. The CacheLength property specifies the size of the buffers for the off-screen items. You specify CacheLength in multiples of the current viewport size. For example, if the CacheLength is 4.0, 2 viewports worth of items are buffered on each side of the viewport. You can set a smaller cache length to optimize startup time, or set a larger cache size to optimize scrolling performance. Item containers that are off-screen are created at a lower priority than those in the viewport.
Upvotes: 0
Reputation: 36072
Your ItemsControl declares both an ItemsSource and a DataContext. I believe these two properties are mutually exclusive - setting the DataContext property disconnects the control from the data associated with the logical control tree.
Remove the DataContext= data binding and I think you'll see the items in the ItemsSource appear in your ItemsControl.
Also, note that ItemsControl doesn't provide any UI definition on its own. For debugging purposes, it can be useful to drop in a ListBox or other concrete ItemsControl and give it the same data binding settings to verify that your data bindings are sane. If the ItemsControl doesn't show anything but the ListBox does, then your problem isn't in data binding, but in templating the ItemsControl visuals.
Upvotes: 0