I am trying to bind a property ObservableCollection<ObservableCollection<Location>> to a ListBox with ItemTemplate of ListBox which in-turn has an ItemTemplate that is a grid. The layout of the listbox within a listbox seems to work fine. However, I am having issues with my databinding.
For the second layer listbox ItemsSource I have tried binding using the Collection Current Item Bindings ItemSource="{Binding /}" and using ItemsSource="{TemplateBinding /}". I new to WPF and am using MVVM, so any tips and/or criticism are appreciated.
<ListBox Grid.Row="4" Width="610" Height="600" HorizontalContentAlignment="Stretch" ItemsSource="{Binding CurrentLocation.Children}">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox Width="550" Height="100" Margin="5" HorizontalContentAlignment="Stretch" ItemsSource="{Binding /}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Margin="5" Text="Name:" />
<TextBlock Grid.Column="0" Grid.Row="1" Margin="5" Text="Description:" />
<TextBlock Grid.Column="1" Grid.Row="0" Margin="5" Text="{Binding Name}" />
<TextBlock Grid.Column="1" Grid.Row="1" Margin="5" Text="{Binding Description}" TextWrapping="Wrap" />
<Button Grid.Column="2" Grid.Row="0" Command="{Binding TODO}">
<TextBlock Text="Edit"/>
</Button>
<Button Grid.Column="2" Grid.Row="1" Command="{Binding TODO}">
<TextBlock Text="Delete"/>
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Each ListBoxItem contains the DataContext of whatever the object is in the parent collection, so you should be fine to specify nothing in the Binding.
<ListBox ItemsSource="{Binding MyCollectionOfCollections}">
<ListBox.ItemTemplate>
<DataTemplate>
<!-- DataContext of each item will an inner ObservableCollection<Location> -->
<ListBox ItemsSource="{Binding }" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The correct notation for binding to the current DataContext as a whole is {Binding}.
<ListBox ... ItemsSource="{Binding CurrentLocation.Children}">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox ... ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Margin="5">
<!-- snip -->
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Related
I have written a DataTemplate in App.xaml.
<DataTemplate x:Key="PlayDVBViewer">
<GroupBox Header="{x:Static properties:Resources.PlayInDVBViewer}" UseLayoutRounding="True" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Static properties:Resources.ChooseDVBViewer}" Margin="5" VerticalAlignment="Center"/>
<ComboBox Grid.Row="1" ItemsSource="{Binding Clients.Items}" SelectedItem="{Binding Client}" SelectedValuePath="Name" DisplayMemberPath="Name" Margin="5" Padding="5" VerticalAlignment="Center" Background="Transparent"/>
<!--<Button Grid.Column="1" Grid.Row="1" x:Name="btnPlay" Click="BtnPlay_Click" Margin="5" Padding="5" VerticalAlignment="Center" Background="Transparent" Content="{x:Static properties:Resources.Playback}"/>-->
<Button Grid.Column="1" Grid.Row="1" Command="{Binding BtnPlayClick}" Margin="5" Padding="5" VerticalAlignment="Center" Background="Transparent" Content="{x:Static properties:Resources.Playback}"/>
</Grid>
</GroupBox>
</DataTemplate>
The template works correctly in a page. But on the same page, in a DataGrid, it doesn't work. Why?
<!--Wiedergabe Optionen -->
<GroupBox Header="{x:Static properties:Resources.Playback}" Grid.Row="1" Grid.Column="2" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" ContentTemplate="{StaticResource ResourceKey=PlayDVBViewer}" Content="{Binding}"/>
</Grid>
</GroupBox>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Grid>
<!-- Detail Grid mit den Buttons zum Abspielen -->
<Grid Grid.Row="0">
<StackPanel Orientation="Horizontal">
<GroupBox Header="{x:Static properties:Resources.Picture}" MinWidth="120" Margin="5">
<Image Height="64" Source="{Binding ImagePath, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PageAufnahmen}}}" Margin="5"/>
</GroupBox>
<ContentPresenter ContentTemplate="{StaticResource PlayDVBViewer}"/>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
Ok, I have found the error.
If you use ContentPresenter in the DataTemplate of a grid. The binding will bind to the selected item. The solution is, use the same binding, like the image in the last box, see my post above.
I have a Listbox with some string and int items. When ALT key is pressed the list items are unlined. I have set in ContentPresenter style like this, RecognizesAccessKey="False". But it is not working. Please anyone suggest me to fix this. The Listbox values are like this, T1_1.
MainWindow
<ListBox
x:Name="dropListBox"
Grid.Row="1"
Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AllowDrop="True"
Background="#F8F8F8"
BorderThickness="0"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
ItemsSource="{Binding DetailsCollection}"
Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Values}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="23"
Height="23"
Source="{Binding State, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IntToImageSourceConverter}}" />
<Label
Grid.Column="1"
Content="{Binding Name}"
FontSize="12" />
<Label
Grid.Column="2"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
Content="{Binding CurrentValue}"
FontSize="12" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have set viewmodel as page's datacontext, and binding pivot items with an Individual collection property. However the binding is working correctly when there is data, but initially when data is not available it is not working properly, I basically want to hide the textbox below the ItemsControl but don't know whats wrong with this code.
<phone:PivotItem Header="Tweets" Margin="{StaticResource PivotItemMargin}" DataContext="{Binding Tweets}">
<ScrollViewer>
<StackPanel>
<ItemsControl ItemsSource="{Binding Result}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="75" />
</Grid.RowDefinitions>
<Image Grid.Column="0" Grid.RowSpan="2" Source="{Binding userImage}" Margin="0,0,10,0" MaxWidth="100" MaxHeight="100" Stretch="UniformToFill" Visibility="{Binding userImage, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding name}" Foreground="{StaticResource AppForegroundHighlightTextBrush}" TextWrapping="NoWrap" TextTrimming="WordEllipsis" FontSize="{StaticResource TitleFontSize}"/>
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding ShortTitle}" Foreground="{StaticResource AppForegroundSubtextBrush}" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="{StaticResource SubtextFontSize}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock DataContext="{Binding Tweet}" Grid.Row="2" Text="all Tweets" FontWeight="Bold" Visibility="{Binding hasMore,Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</ScrollViewer>
</phone:PivotItem>
When DataContext is null, binding will use value specified in TargetNullValue property. Therefore, try to set TargetNullValue property of Visibility binding to Collapsed and you won't even need converter :
.......
<Image
.......
Visibility="{Binding userImage, TargetNullValue=Collapsed}"
/>
.......
I've got 2 listbox and one scrollviewer and I want the scrollviewer to scroll the two listbox together. But i don't know how to do.. Here's my xaml :
<ScrollViewer Grid.Row="1">
<Grid>
<ListBox Name="listboxRSSFeedItems" Width="240" Height="644" Margin="0,0,240,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" Grid.Row="0" FontSize="24" HorizontalAlignment="Left" />
<HyperlinkButton Content="Link to details" NavigateUri="{Binding Link}" HorizontalAlignment="Left" Grid.Row="1" Margin="0,0,0,30" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="listboxRSSFeedItems2" Width="240" Height="644" Margin="240,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" Grid.Row="0" FontSize="24" HorizontalAlignment="Left" />
<HyperlinkButton Content="Link to details" NavigateUri="{Binding Link}" HorizontalAlignment="Left" Grid.Row="1" Margin="0,0,0,30" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</ScrollViewer>
Thanks a lot
Ok. I just tried to do one listbox with grid. it works fine, but how to choose which grid to add my item.
I used to add with "listboxRSSFeedItems.Items.Add(item)", but now, how can i choose the 2nd Column only.
<ScrollViewer Grid.Row="1">
<ListBox x:Name="listboxRSSFeedItems" Width="480" Height="680">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid x:Name="first" Grid.Column="0">
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" />
<HyperlinkButton NavigateUri="{Binding URL}" TargetName="_blank"/>
</Grid>
<Grid x:Name="second" Grid.Column="1">
<TextBlock TextWrapping="Wrap" Text="{Binding Title}" />
<HyperlinkButton NavigateUri="{Binding URL}" TargetName="_blank" />
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
Thanks again
You shouldn't set height of your listBoxes.
ps: Consider layout using columns
<ScrollViewer >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox x:Name="first" Grid.Column="0" />
<ListBox x:Name="second" Grid.Column="1" />
</Grid>
</ScrollViewer>
Set VerticalScrollBarVisibility to "Disabled" for listBoxes.
And it will be better using StackPanel for this puprose instead of Grid.
I have a DataGrid "nested" inside another DataGrid's RowDetailsTemplate. Scrolling works fine whenever my mouse is over the main portion of the row on the parent DataGrid, but when the mouse is over the DataGrid nested inside the RowDetailsTemplate, it stops scrolling.
Here is the DataGrid setup:
<my:DataGrid Margin="-2,36,-2,1"
Background="White"
CanUserReorderColumns="True"
CanUserResizeRows="False"
ColumnHeaderHeight="35"
HorizontalGridLinesBrush="LightGray"
VerticalGridLinesBrush="White"
x:Name="testList"
VerticalScrollBarVisibility="Visible"
FlowDirection="LeftToRight"
AutoGenerateColumns="False"
IsReadOnly="True"
ScrollViewer.CanContentScroll="False"
SelectionMode="Single"
HeadersVisibility="Column"
GridLinesVisibility="None"
>
<my:DataGrid.Columns>
<my:DataGridTemplateColumn MinWidth="60" CanUserSort="True" SortMemberPath="ResultType">
<my:DataGridTemplateColumn.Header>
<TextBlock FontSize="14" Text="Result"></TextBlock>
</my:DataGridTemplateColumn.Header>
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="4" VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Height="35" Width="35" Source="{Binding TestResultImage}" ToolTip="{Binding ResultType}" />
</Grid>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn MinWidth="100" CanUserSort="True" SortMemberPath="TestName">
<my:DataGridTemplateColumn.Header>
<TextBlock Margin="3" FontSize="14" Text="Dates"></TextBlock>
</my:DataGridTemplateColumn.Header>
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock FontSize="14" TextWrapping="Wrap" AllowDrop="True" Text="{Binding TestName}" ToolTip="This test analyzed data from this date" />
</Grid>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn MinWidth="150" Width="*" CanUserSort="True" x:Name="TestDetails" SortMemberPath="Result">
<my:DataGridTemplateColumn.Header>
<TextBlock Margin="4" FontSize="14" Text="Details"></TextBlock>
</my:DataGridTemplateColumn.Header>
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="5" VerticalAlignment="Center">
<TextBlock TextWrapping="Wrap" FontSize="13" Text="{Binding Result}" ToolTip="Click for more details about this test" />
</Grid>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid.Columns>
<my:DataGrid.RowDetailsTemplate>
<DataTemplate>
<Grid>
<my:DataGrid Background="White"
BorderThickness="0"
CanUserReorderColumns="True"
HeadersVisibility="Column"
CanUserResizeRows="False"
ColumnHeaderHeight="25"
ItemsSource="{Binding GuiValidatorResults}"
HorizontalGridLinesBrush="LightGray"
x:Name="validatorList"
VerticalGridLinesBrush="White"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
FlowDirection="LeftToRight"
AutoGenerateColumns="False"
IsReadOnly="True"
ScrollViewer.CanContentScroll="False"
ScrollViewer.ScrollChanged=""
SelectionMode="Single"
MouseDoubleClick="HideAllValidatorDetails"
GridLinesVisibility="Horizontal">
<my:DataGrid.Columns>
<my:DataGridTemplateColumn MinWidth="60" CanUserSort="True" SortMemberPath="ResultType">
<my:DataGridTemplateColumn.Header>
<TextBlock Margin="0" Text="Result"></TextBlock>
</my:DataGridTemplateColumn.Header>
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="0">
<Image Height="25" Width="25" Source="{Binding ValidatorResultImage}" ToolTip="{Binding ResultType}" />
</Grid>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn MinWidth="100" CanUserSort="True" SortMemberPath="DescriptiveTestLabel">
<my:DataGridTemplateColumn.Header>
<TextBlock Margin="0" Text="Validator"></TextBlock>
</my:DataGridTemplateColumn.Header>
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="5">
<TextBlock TextWrapping="Wrap" AllowDrop="True" Text="{Binding DescriptiveTestLabel}" />
</Grid>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn MinWidth="150" Width="*" CanUserSort="True" SortMemberPath="Text">
<my:DataGridTemplateColumn.Header>
<TextBlock Margin="0" Text="Message"></TextBlock>
</my:DataGridTemplateColumn.Header>
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="5">
<TextBlock TextWrapping="Wrap" AllowDrop="True" Text="{Binding Text}" />
</Grid>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid.Columns>
<my:DataGrid.RowDetailsTemplate>
<DataTemplate>
<GroupBox FontWeight="Bold" Margin="5" Header="Additional Details:">
<Grid Margin="5" x:Name="WidthSetter">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Resources>
<DataTemplate x:Key="AdditionalDetailsTemplate">
<Grid>
<DockPanel>
<TextBlock HorizontalAlignment="Left" Margin="0,0,0,10" Text="{Binding Path=.}" TextWrapping="Wrap" />
</DockPanel>
</Grid>
</DataTemplate>
</Grid.Resources>
<ListView FontWeight="Normal"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
HorizontalContentAlignment="Stretch"
BorderThickness="0"
HorizontalAlignment="Left"
Margin="0"
Width="{Binding ActualWidth, ElementName=WidthSetter}" ItemTemplate="{StaticResource AdditionalDetailsTemplate}" ItemsSource="{Binding Path=AdditionalDetails}" />
<Grid Grid.Row="1" Margin="3,5,5,5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock FontWeight="Bold" Text="Records involved:" />
<ListView BorderThickness="0" ItemsSource="{Binding InvolvedRecords}" ItemTemplate="{StaticResource ValidatorInvolvedRecordsTemplate}" Grid.Row="1" />
</Grid>
</Grid>
</GroupBox>
</DataTemplate>
</my:DataGrid.RowDetailsTemplate>
</my:DataGrid>
</Grid>
</DataTemplate>
</my:DataGrid.RowDetailsTemplate>
</my:DataGrid>
I would think that there would be some way to tell the child DataGrid to pass the scroll event up to the "testList" DataGrid, but I haven't been able to figure out how.
Thanks!
Unless the RowDetails is handling the scrolling itself, try setting the property ScrollViewer.CanContentScroll on the main DataGrid to false.
ScrollViewer.CanContentScroll="False"
I found a solution to this problem elsewhere:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e7c3a3b0-3b89-40a3-9160-a930724251fe/nested-datagrid-scrolling-woes?forum=wpf
Which basically says use this method in the CodeBehind:
private void NestedDataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
eventArg.RoutedEvent = UIElement.MouseWheelEvent;
eventArg.Source = sender;
var parent = ((Control)sender).Parent as UIElement;
parent.RaiseEvent(eventArg);
}
And in the xaml the nested DataGrid opening tags contain:
x:Name="NestedDataGrid" PreviewMouseWheel="NestedDataGrid_PreviewMouseWheel"