WPF GridView shared cell template for all columns - wpf

I am trying to create a DataTemplate that can be shared for all columns of a GridView, which has it's columns created dynamically (through code-behind).
I would like to create the DataTemplate as a resource in XAML instead of entirely in code-behind, but I can't figure out how to get the bindings to work properly.
The following is the closest I could come up with (but does not work):
<DataTemplate x:Key="ListViewCellTemplate">
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type GridViewColumn}}}" />
</DataTemplate>
This template is assigned as the CellTemplate of each column as follows:
BindableDataTable table = this.DataContext as BindableDataTable;
foreach (BindableDataColumn c in table.Columns)
{
GridViewColumn col = new GridViewColumn();
col.Header = c.ColumnName;
col.CellTemplate = this.FindResource("ListViewCellTemplate") as DataTemplate;
v.Columns.Add(col);
}

Answer:
Set a DataTemplate in your resources
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="GridViewCellTemplateStyle">
<TextBlock Text="{Binding}">
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding DataContext.CommandDoubleClick, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"/>
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
Create your grid view and make the columns inherit this datatemplate
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="Column1" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
<GridViewColumn Width="Auto" Header="Column2" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
<GridViewColumn Width="Auto" Header="Column3" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
<GridViewColumn Width="Auto" Header="Column4" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
</GridView>
</ListView.View>
</ListView>
This exmaple shows you how to create a double clickable row in a GridViewColumn.
Just change the DataTemplate as you see fit

I'm having the exact same problem.
I want to be able to apply the data template to different columns but have each column bound to a separate data field.
<ListView ItemsSource="{Binding}" Name="listViewIMS" Grid.Row="1" Margin="0,0,0,4" FontSize="11" AlternationCount="2" SelectionMode="Extended">
<ListView.Resources>
<DataTemplate x:Key="Templ">
<TextBlock TextAlignment="Left" Text="{Binding}"/>
</DataTemplate>
<DataTemplate x:Key="Tempr">
<TextBlock Width="78" Margin="-6,0" TextAlignment="Right" Text="{Binding}" />
</DataTemplate>
<Style x:Key="HeaderStyleRight" TargetType="GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style x:Key="HeaderStyleLeft" TargetType="GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView x:Name="gridViewInvoices">
<GridViewColumn Width="80" DisplayMemberBinding="{Binding Document}">
<GridViewColumnHeader Tag="docNo" Content="Document" />
</GridViewColumn>
<GridViewColumn Width="220" DisplayMemberBinding="{Binding Customer}">
<GridViewColumnHeader Tag="customer" Content="Customer"/>
</GridViewColumn>
<GridViewColumn Width="100" DisplayMemberBinding="{Binding inv_date, StringFormat='dd/MM/yy'}" >
<GridViewColumnHeader Tag="date" Content="Date" />
</GridViewColumn>
<GridViewColumn Width="100" DisplayMemberBinding="{Binding inv_l_catalogue}" >
<GridViewColumnHeader Tag="catalogue" Content="Item" />
</GridViewColumn>
<GridViewColumn Width="60" DisplayMemberBinding="{Binding inv_l_qty}" >
<GridViewColumnHeader Tag="qty" Content="Qty" />
</GridViewColumn>
<GridViewColumn Width="80" DisplayMemberBinding="{Binding inv_l_price, StringFormat='0.00' }" >
<GridViewColumnHeader Tag="unitPrice" Content="Price" />
</GridViewColumn>
<GridViewColumn Width="50" DisplayMemberBinding="{Binding inv_l_per}" >
<GridViewColumnHeader Tag="per" Content="Per" />
</GridViewColumn>
<GridViewColumn Header="Goods" CellTemplate ="{StaticResource Tempr}" HeaderContainerStyle="{StaticResource HeaderStyleRight}" Width="80" >
<!--GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="78" Margin="-6,0" TextAlignment="Right" Text="{Binding inv_l_lgoods2, StringFormat='0.00'}" />
</DataTemplate>
</GridViewColumn.CellTemplate>-->
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

#jonathan-beresford
This question is old... But, for future reference:
You can binding on the template
<DataTemplate x:Key="Templ">
<TextBlock TextAlignment="Left" Text="{Binding inv_l_catalogue}"/>
</DataTemplate>

Related

Make the TextBox size adapt to column size in GridView wpf?

Hi I am using a TextBox inside a GridView column cell.
I am correctly able to place and bind the data for the TextBox in the 'Parameter' column.
<ListView Margin="5"
ItemsSource="{Binding Variables}"
Grid.Column="0"
Grid.Row="1"
Width="570">
<ListView.View>
<GridView>
<GridViewColumn Header="Type" Width="40"/>
<GridViewColumn Header="Parameter" Width="80">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding ParameterName}"
Padding="0"
Margin="0"
Width="Auto"
HorizontalContentAlignment="Stretch"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Expression" Width="80"/>
<GridViewColumn Header="Value" Width="50"/>
<GridViewColumn Header="Default Value" Width="80"/>
<GridViewColumn Header="Value Type" Width="80"/>
<GridViewColumn Header="Show in UI" Width="80"/>
<GridViewColumn Header="Description" Width="80"/>
</GridView>
</ListView.View>
</ListView>
I want such that the TextBox width correctly adapts to the width of the 'Parameter' column, even when I try to resize the columns.
I have tried setting the Width and HorizontalContentAlignment properties of TextBox but was not succesful.
Right now it looks like as below:
Can anyone suggest how I can achieve this behavior?
You can add an item container style for ListViewItem that sets the HorizontalContentAlignment to Stretch. You can remove the HorizontalContentAlignment attribute from the TextBox.
<ListView Margin="5"
ItemsSource="{Binding Variables}"
Grid.Column="0"
Grid.Row="1"
Width="570">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Type" Width="40"/>
<GridViewColumn Header="Parameter" Width="80">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding ParameterName}"
Padding="0"
Margin="0"
Width="Auto"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Expression" Width="80"/>
<GridViewColumn Header="Value" Width="50"/>
<GridViewColumn Header="Default Value" Width="80"/>
<GridViewColumn Header="Value Type" Width="80"/>
<GridViewColumn Header="Show in UI" Width="80"/>
<GridViewColumn Header="Description" Width="80"/>
</GridView>
</ListView.View>
</ListView>

WPF how to change text color of a GridViewColumn?

I have this GridViewColumn:
<GridViewColumn Width="180" Header="Status" DisplayMemberBinding="{Binding Status}"/>
Now i want to be able to change this Column text color also via code behind.
I try:
<GridViewColumn Width="180" Header="Status" DisplayMemberBinding="{Binding Status}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding Status}" Foreground="Yellow" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
But it seems that the text color is not changing.
Since you already specifying the celltemplate for each item, you don't need to include the DisplayMemberBinding property, just remove it
<GridViewColumn Width="180" Header="Status">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding Status}" Foreground="Yellow" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

WPF ListView multi columns row

I have this model:
Public Data
{
string name;
string age;
string id;
DateTime time;
}
Currently each ListView row contains all this 4 peoperties:
<ListView.View>
<GridViewColumn Width="20" DisplayMemberBinding="{Binding Index}" />
<GridViewColumn Width="320" DisplayMemberBinding="{Binding Description}" />
<GridViewColumn Width="150" DisplayMemberBinding="{Binding IPAddress}" />
<GridViewColumn Width="150" DisplayMemberBinding="{Binding time}" />
</GridView>
</ListView.View>
Now i want to make this ListView Width smaller so i want to each Row will contain 2 columns with 2 properties on each of them.
Is it possible ?
You need to override the default CellTemplate of GridViewColumn inorder to display your results inside a ListView.View
<GridViewColumn >
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Index}" />
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn >
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding IPAddress}" />
<TextBlock Text="{Binding time}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Don't use a ListView
Use a ListBox DataTemplate with a Grid

Binding a command in a datagrid

I am trying to bind a button withing datagrid to a custom command.
But for some reason, the command dont get executed.
This is the XAML:
<Grid Name="LayoutRoot">
<ListView Name="ListView1"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=id,Mode=OneWay}"
Margin="-6,0,-6,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=name,Mode=OneWay}"
Margin="-6,0,-6,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Path" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=path,Mode=OneWay}"
Margin="-6,0,-6,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Update" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button CommandParameter="{Binding id}" Command="{Binding ???????????}" Content="Edit"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
What should I write instead of the ?????????? in order to show a message with the ID.
Found a solution here:
WPF DataGrid - Button in a column, getting the row from which it came on the Click event handler
I think problem is in Cells DataContext. Within DataTemplate it does not see parent context. Try to add your command to Resources and do something like:
<DataTemplate>
<Button CommandParameter="{Binding id}" Command="{StaticResource yourCommand}" Content="Edit"/>
</DataTemplate>
Create a command Inherit from ICommand interface.
public class ShowMessageWithIdCommand : ICommand
{
// Implement it members
}
in your viewmodel:
public ICommand ShowMessageWithIdCommand
{
get{return new ShowMessageWithIdCommand(...);}
}
Then your ????? will be: ShowMessageWithIdCommand
More detail you can find here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

WPF ListView with GridViewColumn and DataTemplate

I have a CheckedListBox control which is created by adding a DataTemplate with a CheckBox to a ListView. The problem is that I need columns too.
The following code doesn't display the check boxes:
<ListView x:Name="lbDatabases" Height="138" Width="498" Canvas.Left="44" Canvas.Top="146">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding DbName}" Header="Databases" Width="498"/>
</GridView>
</ListView.View>
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}" Checked="AnyChange" Unchecked="AnyChange" Style="{x:Null}" Content="{Binding DbName}"
Width="{Binding CheckWidth}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
However, if I comment out this code, everything works fine but no columns:
<ListView.View>
<GridView >
<GridViewColumn DisplayMemberBinding="{Binding DbName}" Header="Databases" Width="498"/>
</GridView>
</ListView.View>
Is there any way to have it all?
You need to define the data template as CellTemplate for your column:
<ListView x:Name="lbDatabases" Height="138" Width="498" Canvas.Left="44" Canvas.Top="146" >
<ListView.View >
<GridView >
<GridViewColumn Header="Databases" Width="498">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}" Checked="AnyChange" Unchecked="AnyChange" Style="{x:Null}" Content="{Binding DbName}"
Width="{Binding CheckWidth}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
ok after struggling all morning I figured it out. They key here is to use a CellTemplate:
<ListView x:Name="lbDatabases" Height="138" Width="498" Canvas.Left="44" Canvas.Top="146" Style="{StaticResource ListViewStyle}">
<ListView.View >
<GridView>
<GridViewColumn Header="Databases" Width="498">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}" Checked="AnyChange" Unchecked="AnyChange" Style="{x:Null}" Content="{Binding DbName}"
Width="{Binding CheckWidth}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

Resources