Update a XAML control template from C# - c#

I have a control template in XAML that contains a listview with a gridview. I want to bind the listview to a datatable created within C# but I can’t see the listview to do this because it is within a control template. I’ve created the equivalent listview in C# by referencing the control template and its contents and thought that I would be able to use this to set the binding but it hasn’t worked. Does any one have any suggestions?
<ControlTemplate x:Key="HistoryView" TargetType="{x:Type ListViewItem}">
<StackPanel x:Name="stkBonusHistory" Height="400" Visibility="Visible">
<GridViewRowPresenter Content="{TemplateBinding Content}" Columns="{TemplateBinding GridView.ColumnCollection}"/>
<!--this is the listview which I am hoping to turn into the "expander" detail-->
<ListView x:Name="lvBonusHistory" Width="950" Visibility="Visible" Height="300">
<ListView.View>
<GridView x:Name="gvBonusHistory" ColumnHeaderTemplate="{StaticResource GridViewHeader}" >
<GridViewColumn Header="Bonus Start" DisplayMemberBinding="{Binding BonusStart}" Width="150"/>
<GridViewColumn Header="Bonus End" DisplayMemberBinding="{Binding BonusEnd}" Width="150"/>
<GridViewColumn Header="Length" DisplayMemberBinding="{Binding Duration}" Width="75"/>
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding BonusStatus}" Width="75"/>
<GridViewColumn Header="Note" DisplayMemberBinding="{Binding Note}" Width="75"/>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</ControlTemplate>
<ListView x:Name="lvBonusList" Width="1000">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template" Value="{StaticResource Default}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding LeaversBonus}" Value="1">
<Setter Property="Template" Value="{StaticResource LeaversBonus}"/>
</DataTrigger>
<DataTrigger Binding="{Binding HistoryShow}" Value="1">
<Setter Property="Template" Value="{StaticResource Default}"/>
<Setter Property="Template" Value="{StaticResource HistoryView}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView x:Name="gvBonusList" ColumnHeaderTemplate="{StaticResource GridViewHeader}" >
<GridViewColumn x:Name="BonusHistory" Width="20" CellTemplate="{StaticResource BonusHistoryGraphic}" >
</GridViewColumn>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding EmployeeName}" Width="250"/>
<GridViewColumn Header="Emp ID" DisplayMemberBinding="{Binding EmpID}" Width="75"/>
<GridViewColumn Header="Employee Start" DisplayMemberBinding="{Binding EmpStart}" Width="150" />
<GridViewColumn Header="Employee End" DisplayMemberBinding="{Binding EmpEnd}" Width="150"/>
<GridViewColumn Header="Bonus Start" DisplayMemberBinding="{Binding BonusStart}" Width="150"/>
<GridViewColumn Header="Bonus End" DisplayMemberBinding="{Binding BonusEnd}" Width="150"/>
<GridViewColumn Header="Length" DisplayMemberBinding="{Binding Duration}" Width="75"/>
</GridView>
</ListView.View>
</ListView>
Codebehind
private void PopulateBonusHistory()
{
// populates dtBonusHistory
BonusHistoryGet();
ControlTemplate HistoryView = (ControlTemplate)stkBonusList.Resources["HistoryView"];
StackPanel stkBonusHistory = (StackPanel)HistoryView.LoadContent();
(stkBonusHistory.Children[1]).Visibility = Visibility.Collapsed;
ListView lvBonusHistory = (ListView)stkBonusHistory.Children[1];
lvBonusHistory.View = (GridView)(lvBonusHistory.FindName("gvBonusHistory"));
Binding bind = new Binding();
lvBonusHistory.DataContext = dtBonusHistory;
lvBonusHistory.SetBinding(ListView.ItemsSourceProperty, bind);
}

try using
lvBonusHistory.Source = dtBonusHistory;
as thats what you are trying to acheive anyway.

Create an attached property on the parent control then use TemplateBinding inside the ControlTemplate. This way you can pass the source into ControlTemplate.

Related

How to bind background colors of a certain column in WPF ListView?

Right now I use alternating colors:
But for a certain column like Profit, I want to override the background color but with a binding, not a hardcoded color. I have a ProfitColor property in the same Binding class:
<Window.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#1e1e1e"></Setter>
<Setter Property="Foreground" Value="#ffffff"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#3c3c3c"></Setter>
<Setter Property="Foreground" Value="#ffffff"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Viewbox Stretch="Uniform">
<ListView Grid.Row="4" Grid.Column="0" Margin="0,0,0,0" ItemsSource="{Binding Coins}" Name="Tasks" Height="250" AlternationCount="2">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="" Width="25" DisplayMemberBinding="{Binding Path=Value.X}">
</GridViewColumn>
<GridViewColumn Header="" Width="25" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Symbol" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value.Symbol}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Amount" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Unit Price" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Capital" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Profit" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="PNL %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Day %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Hour %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Min %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Lowest" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Price" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value.PriceDecimalDisplay}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Highest" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Vol BTC/h" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Net BTC/m" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Viewbox>
How can I achieve this?

How to set Listviewitem margins to use the Listviewitem's background color?

I am using alternating colors, and it works well, but by default I was getting white lines between the items, i.e. margins/padding, so I set them to 0, which makes it look like this:
But I want some margin between them, it's just when I have margin it looks like this:
How can I make it so that the white margins use the background of the listviewitem?
Here is the xaml code:
<Window.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#1e1e1e"></Setter>
<Setter Property="Foreground" Value="#ffffff"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#3c3c3c"></Setter>
<Setter Property="Foreground" Value="#ffffff"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Viewbox Stretch="Uniform">
<ListView Grid.Row="4" Grid.Column="0" Margin="0,0,0,0" ItemsSource="{Binding Coins}" Name="Tasks" Height="250" AlternationCount="2">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="" Width="25" DisplayMemberBinding="{Binding Path=Value.X}">
</GridViewColumn>
<GridViewColumn Header="" Width="25" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Symbol" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value.Symbol}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Amount" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Unit Price" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Capital" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Profit" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="PNL %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Day %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Hour %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Min %" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Lowest" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Price" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value.PriceDecimalDisplay}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Highest" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Vol BTC/h" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
<GridViewColumn Header="Net BTC/m" Width="90" DisplayMemberBinding="{Binding Path=Value.X}"></GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Viewbox>
What about using a Border instead of a Margin for your ListViewItem?
For example you could set your Border inside a ControlTemplate:
<Style x:Key="BorderedItem" TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Name="Border"
BorderBrush="#1e1e1e"
BorderThickness="0,0,0,10">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then you can set your Style in the ListView:
<ListView ItemContainerStyle="{StaticResource BorderedItem}" />
To change the BorderBrush color depending on your AlternationIndex you could bind it to a property and change it's state from your ViewModel.

Change the text color of a listviewitem in WPF, based on the value of another ListviewItem in the same row

I'd like to change the text color of the "Bedrag" Textblock item to either green or red, based on the value of the first character of the "MarID" listview item in the same row.
When the first character of marID equals 1, the text color should be green, and when it equals 2, the text color should be red.
I've got the following code in my .xaml file:
<ListView x:Name="lstVerrichtingen" HorizontalAlignment="Left" Height="344" Margin="35,28,0,0" VerticalAlignment="Top" Width="934">
<ListView.View>
<GridView>
<GridViewColumn x:Name="gridcolumnVerrichtingID" Header="VerrichtingID" Width="100" DisplayMemberBinding="{Binding VerrichtingID}"/>
<GridViewColumn x:Name="gridcolumnDatum" Header="Datum" Width="100" DisplayMemberBinding="{Binding Datum, StringFormat={}\{0:dd/MM/yyyy\}}"/>
<GridViewColumn x:Name="gridcolumnMarID" Header="MarID" Width="75" DisplayMemberBinding="{Binding MarId}"/>
<GridViewColumn x:Name="gridcolumnBedrag" Header="Bedrag" Width="100" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Bedrag, StringFormat={}{0:0.00}}" TextAlignment="Right" Foreground=""/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="gridcolumnVanAan" Header="VanAan" Width="100" DisplayMemberBinding="{Binding VanAan}"/>
<GridViewColumn x:Name="gridcolumnRekeningNummer" Header="Rekeningnummer" Width="100" DisplayMemberBinding="{Binding RekeningNummer}"/>
</GridView>
</ListView.View>
</ListView>
How can I solve this problem? Thank you.
You can check the MarId binding value using a DataTrigger.
Edit:- I noticed now that you want to check the starting char of the MarId. This can be probably done by a Converter. But by creating a property which returns the first char, you can achieve the same.
public char FirstIDChar
{
get
{
return MarID.ToString().First();
}
}
And your xaml:
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding FirstIDChar}" Value="1">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding FirstIDChar}" Value="2">
<Setter Property="Foreground" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>

How do I make my listview column editable when double clicking?

So I have this listview with a few headers, and when the data is being set I would like to have the option to double click one of the columns to edit the value.
Is this possible and if so what is the proper way of doing so?
<ListView Name="LvProducts" Margin="224,204,10,35">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="120" DisplayMemberBinding="{Binding ID}" />
<GridViewColumn Header="SKU" Width="50" DisplayMemberBinding="{Binding SKU}" />
<GridViewColumn Header="Name" Width="150" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Description" Width="150" DisplayMemberBinding="{Binding Description}" />
<GridViewColumn Header="In Stock" Width="150" DisplayMemberBinding="{Binding InStock}" />
<GridViewColumn Header="Price" Width="150" DisplayMemberBinding="{Binding Price}" />
<GridViewColumn Header="Images" Width="150" DisplayMemberBinding="{Binding Images}" />
</GridView>
</ListView.View>
</ListView>
Answered by Sajeetharan in this post how to make the column editable in ListView?
Create a customized control called EditBox for GridViewColumn.CellTemplate.
In Normal mode, a TextBlock is used to display content; In Editing mode, a TextBox will pop up for editing.
Class inhertied from Control
public class EditBox : Control
{
static EditBox()
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(object),
typeof(EditBox),
new FrameworkPropertyMetadata());
}
Add a dependency Property for IsEditing.
public static DependencyProperty IsEditingProperty =
DependencyProperty.Register(
"IsEditing",
typeof(bool),
typeof(EditBox),
new FrameworkPropertyMetadata(false)
);
Style for the Custom EditBox:
<Style x:Key="{x:Type l:EditBox}" TargetType="{x:Type l:EditBox}" >
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type l:EditBox}">
<TextBlock x:Name="PART_TextBlockPart"
Text="{Binding Path=Value, RelativeSource = {RelativeSource TemplatedParent}}">
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In your Xaml, you can place the EditBox in each column:
//Example with first column
<GridViewColumn Header="ID" Width="120" DisplayMemberBinding="{Binding ID}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<i:EditBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

Align ListView Column Text independently with WPF XAML

I'm learning some WPF controls and am having trouble individually aligning the text in listView columns. I've been able to align them all together, and align the headers, just not the column data itself. I would appreciate some help getting it working.
As a note, this is similar to this question: WPF Listview, align listview item horizontal dynamic not in xaml
I've also tried some other solutions on blogs. While this seems to have been answered, I just can't get it too work. I'd like for the "Filename" column data to be left aligned, and the other two columns center aligned. The headers are fine all centered.
As a side question, what is the preferred method for displaying data like this? The question I referenced alluded to the DataGrid as being easier to work with.
Code:
<ListView x:Name="edtListView" Margin="30,68,30,52" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<EventSetter Event="MouseDoubleClick" Handler="HandleRow_DoubleClick" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<EventSetter Event="Click" Handler="SortHeader_Click"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn x:Name="fileNameColumn" DisplayMemberBinding="{Binding Path}" Width="450" TextBlock.TextAlignment="Left" >
<GridViewColumn.Header>
<GridViewColumnHeader Content="Filename" Tag="Path"/>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding MissedEdts}" Width="50" TextBlock.TextAlignment="Center" >
<GridViewColumn.Header>
<GridViewColumnHeader Content="Missed" Tag="MissedEdts"/>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Notes}" Width="95" TextBlock.TextAlignment="Center" >
<GridViewColumn.Header>
<GridViewColumnHeader Content="Notes" Tag="Notes"/>
</GridViewColumn.Header>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
**EDIT: **
Fixed it doing this:
As referenced a couple places, the "DisplayMemberBinding" takes precedence over anything else. I just needed to define a "DataTemplate" for each column and bind the "TextBlock.Text" to the correct "Binding Path". Then delete the "DisplayMemberBinding" references.
<Window.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<EventSetter Event="Click" Handler="SortHeader_Click"/>
</Style>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<EventSetter Event="MouseDoubleClick" Handler="HandleRow_DoubleClick" />
</Style>
<DataTemplate x:Key="value1Template">
<TextBlock TextAlignment="Left" Text="{Binding Path}"/>
</DataTemplate>
<DataTemplate x:Key="value2Template">
<TextBlock TextAlignment="Center" Text="{Binding MissedEdts}"/>
</DataTemplate>
<DataTemplate x:Key="value3Template">
<TextBlock TextAlignment="Center" Text="{Binding Notes}"/>
</DataTemplate>
</Window.Resources>
<ListView x:Name="edtListView" Margin="30,68,30,52" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.View>
<GridView>
<GridViewColumn x:Name="fileNameColumn" CellTemplate="{StaticResource value1Template}" Width="450" >
<GridViewColumn.Header>
<GridViewColumnHeader Content="Filename" Tag="Path"/>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="50" CellTemplate="{StaticResource value2Template}">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Missed" Tag="MissedEdts"/>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn CellTemplate="{StaticResource value3Template}" Width="95" >
<GridViewColumn.Header>
<GridViewColumnHeader Content="Notes" Tag="Notes"/>
</GridViewColumn.Header>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Easy, your headers automatically use TextBlock's since you didn't specify the container, specify them in each GridViewColumnHeader and you can do what you want with it (oh and you will need to remove your DisplayMemberBinding since we are explicitly defining the content of the header now), e.g.:
<GridViewColumn x:Name="fileNameColumn" Width="450" TextBlock.TextAlignment="Left" >
<GridViewColumn.Header>
<GridViewColumnHeader Content="Filename" Tag="Path">
<TextBlock Text="{Binding Path}" HorizontalTextAlignment="Right" FontSize="100"/> <!--This line-->
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>

Categories