C# WPF Extending ListView row - c#

I have ListView and I want the last item in the row displayed below the actual row items. Raw copy of xaml:
<ListView x:Name="ListViewRotations" FontFamily="Consolas" MouseDoubleClick="ListViewRotations_MouseDoubleClick">
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" Click="ContextMenuItemRemoveClicked" />
</ContextMenu>
</ListView.ContextMenu>
<ListView.View>
<GridView>
<GridViewColumn Width="120" Header="Max Craftsmanship" DisplayMemberBinding="{Binding RotationInfo.MaxCraftsmanship}" />
<GridViewColumn Width="120" Header="Min Craftsmanship" DisplayMemberBinding="{Binding RotationInfo.MinCraftsmanship}" />
<GridViewColumn Width="80" Header="Min Control" DisplayMemberBinding="{Binding RotationInfo.MinControl}" />
<GridViewColumn Width="50" Header="CP" DisplayMemberBinding="{Binding RotationInfo.CP}" />
<GridViewColumn Width="130" Header="Score" DisplayMemberBinding="{Binding RotationInfo.Score}" />
<GridViewColumn Width ="Auto" Header="Rotation Time" DisplayMemberBinding="{Binding RotationInfo.RotationTime}" />
<GridViewColumn Width ="Auto" Header="Rotation" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Images}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="CraftingActionContainer">
<Grid Height="25">
<Image Width="25" Height="25" Source ="{Binding BitmapSource}" VerticalAlignment="Top" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
As you can see, last item is actually a ListBox and since it is quite long I want it to appear on new line.
So far I only thought of creating 2 types of items, one with text data and the other for holding the last item and using template selector. Maybe you know of other ways. Thanks in advance.
Edit:
Images included.
Current result
Wanted result
Generally speaking, is it possible to separate last item from row and modify it so it appears below other items

You can use DataGrid with row details;
<Grid Margin="10">
<DataGrid Name="dgUsers" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Birthday" Binding="{Binding Birthday}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="{Binding Details}" Margin="10" />
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
Full tutorial you can find here: Row Details

Related

XAML binding behaviour on ListView inside ListView data binding

I have a class
Class Test
{
string name {get;set;}
List<string> marks {get; set;}
}
Trying to bind data of ObservableCollection to XAML
<ListView x:Name="list1" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{Binding}" Width="790">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView >
<GridViewColumn Header="Name" HeaderTemplate="{StaticResource myHeaderTemplate}" HeaderContainerStyle="{StaticResource myHeaderStyle}" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="xyt" Text="{Binding name}" TextAlignment="Center" FontFamily="Arial" FontSize="14">
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Marks" HeaderTemplate="{StaticResource myHeaderTemplate}" HeaderContainerStyle="{StaticResource myHeaderStyle}" Width="500">
<GridViewColumn.CellTemplate>
<DataTemplate>
**<ListView x:Name="list2" ItemsSource="{Binding marks}">
<DataTemplate>
<TextBlock x:Name="marki" Text="{Binding}" TextAlignment="Center" FontFamily="Arial" FontSize="16" Margin="10" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown">
</TextBlock>
</DataTemplate>
</ListView>**
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
But I get error in binding "operation-is-not-valid-while-itemssource-is-in-use-access"
When I remove DataTemplate from list2, it shows properly with data binding, with name and corresponding listview of marks.
<ListView x:Name="list1" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{Binding}" Width="790">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView >
<GridViewColumn Header="Name" HeaderTemplate="{StaticResource myHeaderTemplate}" HeaderContainerStyle="{StaticResource myHeaderStyle}" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="xyt" Text="{Binding name}" TextAlignment="Center" FontFamily="Arial" FontSize="14">
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Marks" HeaderTemplate="{StaticResource myHeaderTemplate}" HeaderContainerStyle="{StaticResource myHeaderStyle}" Width="500">
<GridViewColumn.CellTemplate>
<DataTemplate>
**<ListView x:Name="list2" ItemsSource="{Binding marks}">
</ListView>**
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I am assigning datasource as
list1.ItemsSource = observablecollection<Test>;
I tried adding giving Path, relativesource, but still facing error.
I am confused why putting TextBlock causing error?
you are missing <ListView.ItemTemplate> tag around DataTemplate:
<ListView x:Name="list2" ItemsSource="{Binding marks}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="marki" Text="{Binding}" TextAlignment="Center" FontFamily="Arial" FontSize="16" Margin="10" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"/>
</DataTemplate>
<ListView.ItemTemplate>
</ListView>
markup
<ListView>
<DataTemplate>
</DataTemplate>
</ListView>
is equivalent to
<ListView>
<ListView.Items>
<DataTemplate>
</DataTemplate>
<ListView.Items>
</ListView>
and Items usage conflicts with setting ItemsSource.
<ListView.Items> can be omitted because Items property is chosen as ContentProperty for ListView.

Add text on image dynamically in WPF with C#

I am trying to achieve some thing below in the image.
In the list, I would like to put the text "WS1", "WS2" "WS3" onto the image dynamically in the code depending on the some conditions. I have setup something in xaml. I am not sure if that will work and how to write the code to match the xaml.
<Style x:Key="AnnotationStyle" TargetType="TextBlock">
<Setter Property="Background" Value="#70FFFFFF" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<DataTemplate x:Key="DisplayImage">
<StackPanel Width="50">
<StackPanel Orientation="Horizontal">
<Image Height="40" Source="{Binding ImageData}" />
<TextBlock Text="{Binding Description}" Style="{StaticResource AnnotationStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<ListView.View>
<GridView>
<GridViewColumn CellTemplate="{StaticResource checkbox}"/>
<GridViewColumn Header="Profile ID" DisplayMemberBinding="{Binding ProfileID}"/>
<GridViewColumn Header="Monitor 1" DisplayMemberBinding="{Binding DisplayImage}">
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
How do I implement this in the code and does this xaml work? thank you very much in advance.
<ListView>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Width="50"
DisplayMemberBinding="{Binding ProfileID}"
Header="Profile ID" />
<GridViewColumn Width="90" Header="Monitor 1">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Image
Width="50"
Height="40"
Source="{Binding DisplayImage}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Text1}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="90" Header="Monitor 2">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Image
Width="50"
Height="40"
Source="{Binding DisplayImage}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Text2}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="90" Header="Monitor 3">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Image
Width="50"
Height="40"
Source="{Binding DisplayImage}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Text3}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

WPF Delete button in listview mvvm

I have a button inside a listview to delete selected item.when i click on the button RemoveSubjectCommand is not firing. if i put the button outside the listview it is working fine. hopw this is just because of nested item. how can i solve this problem?
<ListView HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3" Grid.Row="2"
ItemsSource="{Binding AssignedSubjects}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Width="140" Header="Subjects" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Width="auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="X" Command="{Binding RemoveSubjectCommand}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
View Model,
private ICommand removeSubjectCommand;
**
public ICommand RemoveSubjectCommand
{
get { return removeSubjectCommand ?? (removeSubjectCommand = new RelayCommand(param => this.RemoveSubject(), null)); }
}
**
private void RemoveSubject()
{ ***
}
If i put following code, it will work fine.
<ListView.InputBindings>
<KeyBinding Key="Delete" Command="{Binding RemoveSubjectCommand}" />
</ListView.InputBindings>
That is because DataContext of button is ListBoxItem DataContext. So you need to go to parent ListView DataContext.
one way to do that, is to give ListView a name, and to bind with element name
<ListView Name="lv" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" Grid.ColumnSpan="3" Grid.Row="2"
ItemsSource="{Binding AssignedSubjects}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Width="140" Header="Subjects" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Width="auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="X" Command="{Binding ElementName=lv,Path=DataContext.RemoveSubjectCommand}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
You need to bind the Command to using FindAncestor. Otherwise, it'll try to bind to a RemoveSubjectCommand using the ListViewItem's datacontext, not the ViewModel's.
Try this:
<Button Content="X" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}, Path=DataContext.RemoveSubjectCommand}" />
if i put the button outside the listview it is working fine
Because RemoveSubjectCommand property is defined in the data context of ListView, not in the data context of item.

How to center a TextBlock within a CellTemplate in WPF?

I tried both HorizontalAlignment and TextAlignment but it has no effect.
<GridViewColumn Width="Auto" Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}" HorizontalAlignment="Center" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Any ideas?
EDIT:
Xaml code:
<Window x:Class="EffectsWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Effects Editor"
<DockPanel VerticalAlignment="Stretch">
<DockPanel.Resources>
<ListView
DockPanel.Dock="Top"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding EditorViewModel.AllEffects}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Name}"
Header="Name" />
<GridViewColumn Width="Auto" Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}" HorizontalAlignment="Center" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<DockPanel Width="100"
Height="100"
Margin="0,0,20,20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<Label Margin="0,0,0,0"
Content="Data"
DockPanel.Dock="Top" />
<ListBox
VerticalAlignment="Top"/>
</DockPanel>
</DockPanel>
</Window>
did you try HorizontalContentAlignment? on the column?
-- EDIT --
turns out it's kinda hard to find the right place to put this HorizontalContentAlignment... :)
use this
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ListView.Resources>
in the listview.
Snoop usually helps u to be on the right path. This ContentPresenter is the used by the ListViewItem, and it gets its Alignment from the ContentAlignment on the ListViewItem. u can't access the ListViewItem directly, and that's why u need that Style
and the full code:
<DockPanel VerticalAlignment="Stretch">
<ListView
DockPanel.Dock="Top"
HorizontalContentAlignment="Stretch"
x:Name="MyListView">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView >
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Name}"
Header="Name" />
<GridViewColumn Width="Auto" Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Type}" HorizontalAlignment="Center" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<DockPanel Width="100"
Height="100"
Margin="0,0,20,20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<Label Margin="0,0,0,0"
Content="Data"
DockPanel.Dock="Top" />
<ListBox
VerticalAlignment="Top"/>
</DockPanel>
</DockPanel>
Unfortunatelly there is no way to adjust the horizontal alignment of TextBlocks within CellTemplate.
Because GridViewRowPresenter sets the HorizontalAlignment property of Cells to HorizontalContentAlignment of its TemplatedParent, which in this case is ListViewItem.
So you are going to have to change your ListViewItemStyle.
If you change the HorizontalContentAlignment of ListViewItem using snoop, you will see that the alignment of cell will not be affected since HorizontalContentAlignment value is set during the creating of the cells.

Add lines to gridview

I'm trying add vertical lines to my grid. I have found some examples but nothing works.
<ListView ItemsSource="{Binding Path=CheckableObjectFacilities}" x:Name="ListViewObjectFacilities" Margin="5">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsChecked}" Click="cboxObjectFacilities_Click" HorizontalContentAlignment="Stretch"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Nazwa" >
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Category}" Header="Kategoria" >
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding EnglishName}" Header="EN" ></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Created lines in your GridView by following the example from the following site: Designer WPF.
Here is some XAML I adapted to display system font information:
<Grid>
<Grid.Resources>
<Style x:Key="MyItemContainerStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</Grid.Resources>
<ListView
ItemContainerStyle="{DynamicResource MyItemContainerStyle}"
ItemsSource="{x:Static Fonts.SystemFontFamilies}"
x:Name="myListView"
Width="Auto">
<ListView.View>
<GridView>
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="#FF000000" BorderThickness="1,1,0,0" Margin="-6,-2,-6,-2">
<StackPanel Margin="6,2,6,2">
<TextBlock Text="{Binding Source}"/>
</StackPanel>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Line Spacing">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="#FF000000" BorderThickness="1,1,0,0" Margin="-6,-2,-6,-2">
<StackPanel Margin="6,2,6,2">
<TextBlock Text="{Binding LineSpacing}"/>
</StackPanel>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Sample">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="#FF000000" BorderThickness="1,1,1,0" Margin="-6,-2,-6,-2">
<StackPanel Margin="6,2,6,2">
<TextBlock FontFamily="{Binding}" FontSize="20"
Text="ABCDEFGabcdefg" />
</StackPanel>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>

Categories