Hierarchical data binding with nested ListViews in WPF - wpf

I have some data that has a detail table. I want the data to be presented in a ListView. I want the detail data to appear as a nested ListView when you select an item in the original list. I can't seem to figure out how to get the data binding to work.
Here's what I have so far, (the problem is the {Binding Path=FK_History_HistoryItems}):
<ListView Name="lstHistory" ItemsSource="{Binding Source={StaticResource History}}" SelectionChanged="lstHistory_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Name" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Description}" Header="Description" Width="150" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Total, Converter={StaticResource moneyConvert}}" Header="Total" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding Converter={StaticResource categoryAggregate}}" Header="Categories" Width="100" />
</GridView>
</ListView.View>
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border>
<StackPanel>
<Border Name="presenter"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<GridViewRowPresenter />
</Border>
<Border Name="details" Visibility="Collapsed" Margin="5"
BorderBrush="Black" BorderThickness="2">
<StackPanel Margin="5">
<ListView ItemsSource="{Binding Path=FK_History_HistoryItems}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=Ammount}" Header="Ammount" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Category}" Header="Category" Width="100" />
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Border>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="details" Property="Visibility" Value="Visible" />
<Setter TargetName="presenter" Property="Background" Value="Navy"/>
<Setter TargetName="presenter" Property="TextElement.Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
</ListView>

If I understand your question correctly you need to bind to the SelectedItem of the original list:
<ListView ItemsSource="{Binding ElementName=lstHistory, Path=SelectedItem}">
And then set the datatemplate/view as needed. If you don't want to use ElementName for the binding you could also use RelativeSource but I find ElementName is easier to read and understand.

You need to change your problem line to the following:
<ListView ItemsSource="{Binding FK_History_HistoryItems}">
With that change, the control works beautifully. I have been working on something similar to no avail. I really like your work on this.

In order to get the Trigger to work, You will need to set the ControlTemplate TargetType:
<ControlTemplate TargetType="{x:Type ListViewItem}">
Without the TargetType being specified (as a Selectable type), the XAML rendering will be confused...

Related

How to have a GridView as a ContextMenu

Is it possible (if so how) to have a GridView control appear as a ContextMenu? When I tried following patterns which use a StackPanel as the ItemsPresenter, and naively used a ListView/GridView in its place, like the below, I receive the error "VisualTree of ItemsPanelTemplate must contain a Panel. 'System.Windows.Controls.ListView' is not a Panel." which specifies the problem, but how can I fix it/achieve what I want to do?
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding Source={x:Static local:Data.CurrentTimetabling},
Path=TheSemesters[0].SharedViews}">
<ContextMenu.Template>
<ControlTemplate TargetType="ContextMenu">
<ItemsPresenter Margin="0,5"/>
</ControlTemplate>
</ContextMenu.Template>
<ContextMenu.ItemsPanel>
<ItemsPanelTemplate>
<ListView>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView.View>
</ListView>
</ItemsPanelTemplate>
</ContextMenu.ItemsPanel>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<ContentPresenter ContentSource="Header"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
<Button.ContextMenu>

Applying a ControlTemplate Trigger to a CheckBox in a ListView

I am trying to override the appearance of a CheckBox in a ListView. The CheckBox is bound to a nullable bool (bool?).
The style does not seem to be applied at all. What am I doing wrong here?
<ListView Grid.Row="1" Margin="10" VerticalAlignment="Top" ItemsSource="{Binding Prerequisites}" d:DataContext="{d:DesignInstance Type=viewModels:MockPrerequisiteViewModel, IsDesignTimeCreatable=True}">
<ListView.Resources>
<Style x:Key="StyleCustomCheckBox" TargetType="{x:Type CheckBox}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="10,0,0,0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<StackPanel Orientation="Horizontal">
<Path x:Name="MyIcon" Width="18" Height="18" Stretch="Fill" Fill="#FF00FF00"
Data="M-150.204,626.126C-152.317,626.126 -154.429,626.126 -156.541,626.126 -167.642,633.42 -180.629,646.047 -189.668,657.238 -190.916,658.782 -192.945,662.362 -193.701,662.422 -194.041,662.448 -198.024,659.719 -198.614,659.297 -202.818,656.279 -205.779,653.709 -209.257,650.899 -211.248,652.172 -212.879,653.805 -214.153,655.797 -206.627,665.074 -200.283,675.534 -193.124,685.18 -181.491,665.11 -168.473,644.683 -152.796,629.006 -151.735,627.946 -149.817,626.933 -150.204,626.126z"/>
<ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="MyIcon" Property="Data" Value="F1M-1774.05,-6263.81L-1787.51,-6277.27 -1773.22,-6291.56C-1769.23,-6295.55 -1769.24,-6302.03 -1773.21,-6306.01 -1777.19,-6309.98 -1783.67,-6309.99 -1787.66,-6305.99L-1801.95,-6291.71 -1816.79,-6306.55C-1820.79,-6310.55 -1827.26,-6310.54 -1831.24,-6306.55 -1835.22,-6302.58 -1835.23,-6296.11 -1831.24,-6292.12L-1816.39,-6277.27 -1830.4,-6263.25C-1834.4,-6259.26 -1834.38,-6252.8 -1830.4,-6248.82 -1826.42,-6244.84 -1819.96,-6244.82 -1815.96,-6248.82L-1801.95,-6262.83 -1788.49,-6249.37C-1784.5,-6245.38 -1778.03,-6245.39 -1774.06,-6249.37 -1770.07,-6253.35 -1770.06,-6259.82 -1774.05,-6263.81" />
<Setter TargetName="MyIcon" Property="Fill" Value="#FFFF0000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="Machine" DisplayMemberBinding="{Binding Context.Hostname}"/>
<GridViewColumn Width="Auto" Header="Prerequisite" DisplayMemberBinding="{Binding Label}"/>
<GridViewColumn Width="Auto" Header="Status" DisplayMemberBinding="{Binding Status}"/>
<GridViewColumn Width="Auto" Header="Result" DisplayMemberBinding="{Binding Result}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Result}" IsThreeState="True" IsEnabled="False" Style="{StaticResource StyleCustomCheckBox}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
You need to remove the DisplayMemberBinding="{Binding Result}" from the GridViewColumn.
As you are binding the checkbox to result already, and when you set DisplayMemberBinding property, GridView automatically uses a string representation.
<GridViewColumn Width="Auto" Header="Result">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Result}" IsThreeState="True" IsEnabled="False" Style="{StaticResource StyleCustomCheckBox}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

Cannot select ListView item when clicking on some parts

I create a ListView having a GridView like below:
<ListView ItemsSource="{Binding Orders}" SelectedItem="{Binding SelectedOrder}">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListViewItem}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border BorderBrush="SteelBlue" BorderThickness="1" x:Name="Border" Padding="10">
<GridViewRowPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView d:DataContext="{d:DesignInstance entities:ExecReport}">
<GridViewColumn Header="Symbol" DisplayMemberBinding="{Binding Instrument.Symbol}" />
<GridViewColumn Header="Side" DisplayMemberBinding="{Binding Side}" />
<GridViewColumn Header="Price" DisplayMemberBinding="{Binding Price}" />
<GridViewColumn Header="Total Size" DisplayMemberBinding="{Binding Qty}" />
<GridViewColumn Header="Open Size" DisplayMemberBinding="{Binding OpenQty}" />
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding State}" />
<GridViewColumn Header="Validity" DisplayMemberBinding="{Binding Validity}" />
<GridViewColumn Header="Order Seq" DisplayMemberBinding="{Binding OrderSeq}" />
</GridView>
</ListView.View>
</ListView>
I can select items by clicking on them in most places. But when I click on some places they do not get selected. The backing field is not set either. This problem does not happen if I remove the ListViewItem Style.
The below image points out the sort of place where an item does not get selected.
How do I fix this?
Set the Background property of your Border(named "Border") to Transparent. Since controls without background will be considered as hollow and hit test may not be possible. More information on HitTesting.

Unable to apply trigger on TextBlock within ListView/GridView

Unable apply the Style on GridViewDataTemplate field.
I just need to change the Forground of the TextBlock based on its contect.
If pull this textblock outside the list view it works perfectly. But inside the ListView it's not working.
Please let me how to fix this issue.
<ListView Margin="5,15,0,5"
ItemsSource="{Binding}" Background="Transparent" Foreground="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" BorderThickness="0"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
<DataTemplate x:Key="DataColumnStyle" DataType="GridViewColumn.CellTemplate">
<StackPanel>
<TextBlock Text="{Binding}" Foreground="White" FontSize="16" TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="StatusColumnStyle" DataType="GridViewColumn.CellTemplate">
<StackPanel>
<TextBlock Text="{Binding}" FontSize="16" TextWrapping="Wrap">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text" Value="In Progress">
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="Text" Value="Complete">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
<Trigger Property="Text" Value="Failed">
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Activity}" CellTemplate="{StaticResource DataColumnStyle}" x:Name="ActivityColumn"/>
<GridViewColumn DisplayMemberBinding="{Binding Status}" CellTemplate="{StaticResource StatusColumnStyle}" Width="100" x:Name="StatusColumn"/>
</GridView>
</ListView.View>
</ListView>
I believe if you set the DisplayMemberBinding property, the CellTemplate property will be ignored; DisplayMemberBinding is fine if you're only looking to specify text, rather than a template.
So you'd need to change your code to something along these lines:
Altering the Text binding within the `DataTemplate':
Text="{Binding}" => Text="{Binding Activity}"
Removing the DisplayMemberBinding from the ListView:
<GridViewColumn DisplayMemberBinding="{Binding Activity}" CellTemplate="{StaticResource DataColumnStyle}" x:Name="ActivityColumn"/> => <GridViewColumn CellTemplate="{StaticResource DataColumnStyle}" x:Name="ActivityColumn"/>
Roughly:
<!-- Your Code -->
<GridView>
<GridViewColumn CellTemplate="{StaticResource DataColumnStyle}" x:Name="ActivityColumn"/>
<GridViewColumn CellTemplate="{StaticResource StatusColumnStyle}" Width="100" x:Name="StatusColumn"/>
</GridView>
<!-- Your Code -->
If you have a look at the MSDN info for DisplayMemberInfo (also CellTemplate / CellTemplateSelector), you can see that there is an order of precedence:
The following properties are all used to define the content and style
of a column cell, and are listed here in their order of precedence,
from highest to lowest:
DisplayMemberBinding
CellTemplate
CellTemplateSelector

How can I change the fontsize of a GridviewColumnHeader?

I included everything below since it's not that much. I wasn't sure if something I put elsewhere was causing my setter to not work properly.
<ListView x:Name="lvReports"
SelectionMode="Single"
ItemsSource="{Binding reportsCollection}" Height="432" ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ListView.Resources>
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="TextElement.FontSize" Value="30pt"/>
<Setter Property="Width" Value="800"/>
</Style>
</ListView.Resources>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<DockPanel>
<DockPanel Height="30" VerticalAlignment="Bottom">
<Image Source="\Images\ProductivityByEmployeesReport.png"/>
<TextBlock FontWeight="Bold" FontSize="18pt" Text="{Binding Path=Name}"/>
</DockPanel>
</DockPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn x:Name="colName" HeaderContainerStyle="{StaticResource myHeaderStyle}" Header="Reports">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DockPanel>
<Rectangle Width="18"/>
<CheckBox>
<TextBlock Text="{Binding displayName}"/>
</CheckBox>
</DockPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Thanks in advance.
Add this to <ListView.Resources>
<Style TargetType="GridViewColumnHeader" x:Key="ColumnHeaderLarge">
<Setter Property="FontSize" Value="14"/>
</Style>
To set Fontsize to 14, use the style as:
<GridView ColumnHeaderContainerStyle="{StaticResource ColumnHeaderLarge}">

Resources