WPF nested ItemsControl binding issue - wpf

Why is the second ItemsControl binding to FirstName not working?
<ItemsControl Grid.Row="1" x:Name="PMItmsControl" VerticalAlignment="Top" ItemsSource="{Binding FirstEntityCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border CornerRadius="5" BorderBrush="YellowGreen" BorderThickness="1" Margin="5">
<Grid Width="auto" Height="100" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60*"/>
<ColumnDefinition Width="40*"/>
</Grid.ColumnDefinitions>
<TextBlock **x:Name="tb"** Width="100" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" Text="{Binding FirstName}" FontSize="10" >
</TextBlock>
<ItemsControl ItemsSource="{Binding SecondEntityCollection}" Grid.Column="1" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding SecondName}" Margin="5" Foreground="White" />
<TextBlock Grid.Column="1" Text="{Binding **Path= Text, ElementName=tb**}" Margin="5" Width="40">
</TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and in my code behind, i declare following classes:
public class FirstEntity
{
public string FirstName { get; set; }
public ObservableCollection<SecondEntity> SecondEntityCollection { get; set; }
}
public class SecondEntity
{
public string SecondName { get; set; }
}
and the FirstEntityCollection is declare as following in my code behind:
public ObservableCollection<FirstEntity> FirstEntityCollection {get;set;}
not sure if i make my issue clear?
can someone give me any idea? please.
thanks much. very appreciate.
updated: I just found another solution use x:Name="tb" to above Bold code. and then changes Text="{Binding Path= DataContext.FirstName, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ItemsControl},AncestorLevel=2}}" to Text="{Binding Text,ElementName=tb}"
thanks Maxi.
----------------updated again-------------
this is the first time I asked question in stackoverflow, the question editor is not easy to input code and comments and the formatting is so bad, maybe I don't find a easy way to use. anyway thanks.

The first mess-up you need to get rid of is setting Foreground="White" on the TextBlock.
Based on your question update, please find below XAML bindings.
<ItemsControl Grid.Row="1" x:Name="PMItmsControl" VerticalAlignment="Top" ItemsSource="{Binding FirstEntityCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border CornerRadius="5" BorderBrush="YellowGreen" BorderThickness="1" Margin="5">
<Grid Width="auto" Height="100" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60*"/>
<ColumnDefinition Width="40*"/>
</Grid.ColumnDefinitions>
<TextBlock Width="100" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" Text="{Binding FirstName}" FontSize="10" >
</TextBlock>
<ItemsControl ItemsSource="{Binding SecondEntityCollection}" Grid.Column="1" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding SecondName}" Margin="5" />
<!--Notice setting DataContext to TextBlock below-->
<TextBlock Grid.Column="1" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ItemsControl}}}" Text="{Binding Path= FirstName}" Margin="5" Width="Auto"/> </Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Hope this give you an idea to start with...

Related

Listbox items not wrapping, tried almost everything. it might be due to ItemTemplate

**Tried adding wrap panel as parent, as child, as item template parent, but didn't work
**
<UserControl.Resources>
<DataTemplate x:Key="CredentialTemplate" DataType="{x:Type local:Credentials}">
<WrapPanel Width="800" Orientation="Horizontal">
<Grid Background="Red" Width="160" Height="160">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding FileName}" FontWeight="Bold" Margin="0,0,10,0"/>
<Button Grid.Row="1" Grid.Column="0" x:Name="btnCopyUsername" Tag="{Binding Button}" Content="Copy Username" Click="OnCopyUsernameButtonClicked" Margin="10"/>
<Button Grid.Row="1" Grid.Column="1" x:Name="btnCopyPassword" Tag="{Binding Button}" Content="Copy Password" Click="OnCopyPasswordButtonClicked" Margin="10"/>
<Button Grid.Row="2" Grid.Column="0" x:Name="btnEdit" Tag="{Binding Button}" Content="Edit" Click="OnEditButtonClicked" Margin="10"/>
<Button Grid.Row="2" Grid.Column="1" x:Name="btnCopyBoth" Tag="{Binding Button}" Content="Copy Both" Click="OnCopyBothButtonClicked" Margin="10"/>
</Grid>
</WrapPanel>
</DataTemplate>
</UserControl.Resources>
<WrapPanel Width="900" Background="Yellow">
<ListBox ItemsSource="{Binding Credentials}" ItemTemplate="{StaticResource CredentialTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Background="Green" Margin="10"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</WrapPanel>
</UserControl>
It might be the grid control that not letting wrap, normally without item template it should work
Screenshot
I explored this issue with a simplified version of your markup.
I don't have a credentials class, but what's in the grids doesn't matter.
My markup has less wrappanels:
<Grid>
<Grid.Resources>
<DataTemplate x:Key="CredentialTemplate">
<Grid Background="Red" Width="40" Height="40">
</Grid>
</DataTemplate>
</Grid.Resources>
<ListBox ItemsSource="{Binding Points}"
ItemTemplate="{StaticResource CredentialTemplate}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"
Background="Green" Margin="10"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
I've got 30 Points in my viewmodel.
My grid is smaller
Wraps ok:

vertical scroll bar shifts contents horizontally

I an using a Scrollviewer with an ItemsControl in it.
the VerticalScrollBarVisibility of the Scrollviewer is set to "Auto".
the problem is that when the scrollbar appears it shifts the contents of the ItemsControl horizontally.
Is there a way that the scroll bar will just be "over" the contents with out moving them?
the code looks something like this
<ScrollViewer VerticalScrollBarVisibility="Auto" CanContentScroll="True" SnapsToDevicePixels="True">
<ItemsControl ItemsSource="{Binding Summaries}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" IsItemsHost="True" CanVerticallyScroll="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="15,5,10,5" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".166*"></ColumnDefinition>
<ColumnDefinition Width=".166*"></ColumnDefinition>
<ColumnDefinition Width=".166*"></ColumnDefinition>
<ColumnDefinition Width=".166*"></ColumnDefinition>
<ColumnDefinition Width=".166*"></ColumnDefinition>
<ColumnDefinition Width=".166*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Label Grid.Column="1" Content="{Binding A}" HorizontalContentAlignment="Center"/>
<Label Grid.Column="2" Content="{Binding B}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
<Label Grid.Column="3" Content="{Binding C}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
<Label Grid.Column="4" Content="{Binding D}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
<Label Grid.Column="5" Content="{Binding E}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl></ScrollViewer>
Thanks
here is a trick I used recently in my project:
ItemsControl.Width is obtained from ScrollViewer.ActualWidth via OneWay binding:
<ScrollViewer VerticalScrollBarVisibility="Auto" CanContentScroll="True"
Name="scroller"
SnapsToDevicePixels="True">
<ItemsControl ItemsSource="{Binding Summaries}"
Width="{Binding Path=ActualWidth, ElementName=scroller, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" IsItemsHost="True" CanVerticallyScroll="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<UniformGrid Columns="6" Margin="15,5,10,5" HorizontalAlignment="Stretch">
<Label Content="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Label Content="{Binding A}" HorizontalContentAlignment="Center"/>
<Label Content="{Binding B}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
<Label Content="{Binding C}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
<Label Content="{Binding D}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
<Label Content="{Binding E}" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch"/>
</UniformGrid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
also consider using of UniformGrid

Nested ItemsControl Orientation

I have a nested ItemsControl. My data structure is an ObservableCollection of Campaigns which consist of a Campaign class and an observableCollection of Data counts (total, assigned, unassigned, closed). What I need is the following:
CAMPAIGN.NAME
TOTAL UNASSIGNED ASSIGNED CLOSED
CAMPAIGN.NAME
TOTAL UNASSIGNED ASSIGNED CLOSED
I am able to get the first part of this, but for some reason it will not honor the orientation for the second ItemsControl. What am I missing? My XAML is:
<ItemsControl x:Name="icCampaignChicklets" ItemsSource="{Binding CampChicks}" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="gridContent">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Name="CampaignHeader" Height="20" Text="{Binding Path=Campaign.Name}" Grid.Row="1" VerticalAlignment="Top" TextWrapping="Wrap" HorizontalAlignment="Left" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10">
<ItemsControl x:Name="icChicklets" ItemsSource="{Binding Path=Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" Height="140" Background="{Binding Background}" Cursor="Hand"
MouseLeftButtonDown="Chicklet_MouseLeftButtonDown"
>
<Grid x:Name="gridContent" Margin="8,4">
<TextBlock Text="{Binding Caption}" Foreground="White" FontSize="17" />
<TextBlock Text="{Binding CountCaption, Mode=OneWay}" Foreground="White" FontSize="45" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="7" />
<TextBlock Text="Ú" Foreground="#99ffffff" FontSize="30" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="3,5" FontFamily="Wingdings 3" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you want to change the orientation of the contents of an ItemsControl, set its ItemsPanel property like so:
<ItemsControl
...attributes...
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Wrapping it in a horizontally-oriented parent StackPanel will merely arrange it and its siblings horizontally, but in this particular case it has no siblings.

WPF Popup Panel take needed space

I'm having an issue making a popup notification panel take only the amount of space it's inner controls require.
What I've Got:
<Grid>
<DockPanel Panel.ZIndex="1111" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Visibility="{Binding MessageVisibility}">
<Button Visibility="Collapsed" Name="clickButton" Command="{Binding Path=CloseMessage}"/>
<Border Background="LightGray" CornerRadius="20" MouseDown="Border_MouseDown" BorderThickness="8" BorderBrush="CadetBlue">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20px">
<ItemsControl Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Messages}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock TextBlock.TextAlignment="Center" Text="{Binding FallbackValue='Message'}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Border>
</DockPanel>
<DockPanel Panel.ZIndex="0">
...
</DockPanel>
</Grid>
I'm trying to make the first DockPanel only take up the space required by the ItemsControl. It seems to be taking the whole space. Setting a Width/Heigh will keep it in the center but it will not let it grow.
Changing from DockPanel to Stackpanel and setting Hor/Vert alignment center worked.
The below modified code might be helpful and solve your pro
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinitions/>
</Grid.ColumnDefinitions>
<DockPanel Panel.ZIndex="1111" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Visibility="{Binding MessageVisibility}">
<Button Visibility="Collapsed" Name="clickButton" Command="{Binding Path=CloseMessage}"/>
<Border Background="LightGray" CornerRadius="20" MouseDown="Border_MouseDown" BorderThickness="8" BorderBrush="CadetBlue">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Margin="20px">
<ItemsControl Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Messages}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock TextBlock.TextAlignment="Center" Text="{Binding FallbackValue='Message'}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</Border>
</DockPanel>
<DockPanel Panel.ZIndex="0" Grid.Column="0" Grid.Row="1">
...
</DockPanel>
</Grid>

WPF Nested Databinding

I'm trying to bind data into nested StackPanels in WPF using the following code - to no avail. Can anybody spot where I'm going wrong?
<Page.Resources>
<DataTemplate x:Key="MinuteTimeSlotTemplate">
<TextBlock Text="{Binding Path=TourName}" Background="Blue" />
</DataTemplate>
<DataTemplate x:Key="HourlyTimeSlotTemplate">
<StackPanel>
<Border Height="120" BorderThickness="0,0,0,1" BorderBrush="#DDD" x:Name="parentRow">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="123"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="0,0,10,0" MouseUp="StackPanel_MouseUp_1">
<TextBlock Foreground="#4585B9" FontWeight="Bold" FontFamily="Trebuchet MS" FontSize="20" HorizontalAlignment="Right">
<Run Text="{Binding Path=Time}"/></TextBlock>
<TextBlock FontFamily="Trebuchet MS" Foreground="#808080" HorizontalAlignment="Right"><Run Text="View Bookings"/></TextBlock>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="1" Margin="10,0,10,0" x:Name="stk">
<ItemsControl ItemTemplate="{StaticResource MinuteTimeSlotTemplate}" ItemsSource="{Binding Path=HourlySlots}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
</Border>
</StackPanel>
</DataTemplate>
</Page.Resources>
<helpers:AnimatedScrollViewer x:Name="scrlHours" Grid.Column="1" PanningMode="Both" PanningDeceleration="5" PanningRatio="2">
<ItemsControl x:Name="TimeSlotList" ItemTemplate="{StaticResource HourlyTimeSlotTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</helpers:AnimatedScrollViewer>
I set the parent StackPanels ItemsSource in code:
public HourlyCalendar() {
InitializeComponent();
TimeSlotList.ItemsSource = new Models.TimeSlots(DateTime.Today).HourlySlots;
}
And here's my model:
public class TimeSlots {
public TimeSlots(DateTime? day) {
this.HourlySlots = DataManager.GetCalendarDayTimeSlots(day);
}
public IEnumerable<TimeSlot> HourlySlots { get; set; }
}
The parent StackPanel binds as expected, but I cannot figure out how to bind the child StackPanel...
Turns out it was rather simple:
<helpers:AnimatedScrollViewer x:Name="scrlHours" Grid.Column="1" PanningMode="Both" PanningDeceleration="5" PanningRatio="2">
<ItemsControl x:Name="TimeSlots">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Height="120" BorderThickness="0,0,0,1" BorderBrush="#DDD" x:Name="parentRow">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="0,0,10,0" Width="123" MouseUp="StackPanel_MouseUp_1"> <!--Height="{Binding Height, ElementName=parentRow}"-->
<TextBlock Foreground="#4585B9" FontWeight="Bold" FontFamily="Trebuchet MS" FontSize="20" HorizontalAlignment="Right">
<Run Text="{Binding Path=Time}"/></TextBlock>
<TextBlock FontFamily="Trebuchet MS" Foreground="#808080" HorizontalAlignment="Right"><Run Text="View Bookings"/></TextBlock>
</StackPanel>
<ListView ItemsSource="{Binding Bookings}" ScrollViewer.CanContentScroll="False">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TourName}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListView>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</helpers:AnimatedScrollViewer>

Resources