I need to create a common DataGridTemplateColumn, so that I can use it across my application with different objects and properties.
here is some sample code, I use in my project
<DataGridTemplateColumn Width="100*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
I need a generic version of the code so that I can place the DataTemplate in app.xaml and reference it in my code
You can't template DataGridTemplateColumn directly. But fortunately you can use global templates for cells. Take a look at example:
App.xaml
<Application.Resources>
<DataTemplate x:Key="CellEdintingTemplate">
<TextBox Text="{Binding Path=Age}" />
</DataTemplate>
<DataTemplate x:Key="CellTemplate">
<TextBlock Text="{Binding Path=Age}" />
</DataTemplate>
</Application.Resources>
Using
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn
CellEditingTemplate="{StaticResource CellEdintingTemplate}"
CellTemplate="{StaticResource CellTemplate}" />
</DataGrid.Columns>
</DataGrid>
Related
I have a datagrid with three columns.
<DataGrid IemSource={Binding SomeData}>
<DataGrid.Columns>
<DataGridTemplateColumn>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<ItemsControl ItemSource="{Binding SomeList}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox ItemSource="{Binding }"/>
</StackPanel>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
SomeData is a object collection of ClassA. Class A contains two string fields and I have binded them to the first 2 columns.
The class contains a List of string variables of which the name is SomeList. I have binded it to the 3rd column. I need to attach it to the combobox in the header of column 3. But this code does not give me what I want.
can someone help ?
Your problem seems to be that you add the StackPanel as item to the ItemsControl instead of using it in a DataTemplate.
Instead of
<ItemsControl ItemSource="{Binding SomeList}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox ItemSource="{Binding }"/>
</StackPanel>
</ItemsControl>
it should look like this:
<ItemsControl ItemSource="{Binding SomeList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox ItemSource="{Binding }"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have a datagrid like in the following.
.............
<DataGridTemplateColumn >
<DataGridTemplateColumn.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox/>
</StackPanel>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
I want that column to have a combobox in its header. At the same time, I want all the rows in the datagrid to have comboboxes under the same column.
That's what I've written to achieve this. Everything is fine. But in the header what it shows is "System.Windows.Controls.Stackpanel".....It does not show the combobox in the header....not even the topic "sometopic".
where have I gone wrong ?
Can someone answer pls ?
You need to use the DataGridColumn.HeaderTemplate Property instead.
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I'm writing a UserControl with two DataTemplates in the resources:
DataTemplate 1
<DataTemplate x:Key="Template1">
<DataGrid ItemsSource="{Binding}" SelectionChanged="DataGridSelectionChanged">
<DataGrid.Columns>
<DataGridTemplateColumn Header="FilePath" Width="Auto" SortMemberPath="FilePath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FilePath}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="FileSize" Width="Auto" SortMemberPath="FileSize">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileSize}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
DataTemplate2
<DataTemplate x:Key="Template2">
<DataGrid ItemsSource="{Binding}" SelectionChanged="DataGridSelectionChanged">
<DataGrid.Columns>
<DataGridTemplateColumn Header="FilePath" Width="Auto" SortMemberPath="FilePath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FilePath}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="FileSize" Width="Auto" SortMemberPath="FileSize">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileSize}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="FileCreator" Width="Auto" SortMemberPath="FileCreator">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileCreator}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="FileCreated" Width="Auto" SortMemberPath="FileCreated">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileCreated}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
With a DataTemplateSelector I decide which DataTemplate should be used. Everything just works fine.
But as you can see DataTemplate2 has the same two cells as DataTemplate1 plus two additional. This is just an small example. In my application DataTemplate1 has around 15 columns. And with DataTemplate2 there are another 10 columns.
My question now is: Is there a possibility that I can inherit(or so) the columns from another DataGrid inside a DataTemplate and add additional columns?
You can add the Columns as Resource and Refer them in the DataGrid as resources. Make sure you should marked them as x:Shared as false to avoid the conflict.
Refer below code.
<DataGridTemplateColumn x:Key="FilePath" x:Shared="False" Header="FilePath" Width="Auto" SortMemberPath="FilePath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FilePath}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn x:Key="FileSize" x:Shared="False" Header="FileSize" Width="Auto" SortMemberPath="FileSize">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileSize}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataTemplate x:Key="Template1">
<DataGrid ItemsSource="{Binding}" SelectionChanged="DataGridSelectionChanged">
<DataGrid.Columns>
<StaticResource ResourceKey="FilePath"/>
<StaticResource ResourceKey="FileSize"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
<DataTemplate x:Key="Template2">
<DataGrid ItemsSource="{Binding}" SelectionChanged="DataGridSelectionChanged">
<DataGrid.Columns>
<StaticResource ResourceKey="FilePath"/>
<StaticResource ResourceKey="FileSize"/>
<DataGridTemplateColumn Header="FileCreator" Width="Auto" SortMemberPath="FileCreator">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileCreator}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="FileCreated" Width="Auto" SortMemberPath="FileCreated">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="4,1" Text="{Binding FileCreated}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
Refer this link as well WPF DataGrid Columns in Style or resource
AFAIK there is no inherit possibility in columns in datagrid, but what I suggest is --
Create a customGrid control and add all the common columns to it.
Use this grid in your template and add the columns that make sense for that template.
So you will have, BaseGrid with columns 1,2,3,4 and then you can use this baseGrid and add columns 5,6 in one template and 7,8 in another template.
You will have 2 resulting grids, one with columns 1,2,3,4,5,6 and another with 1,2,3,4,7,8
DataGrid.Columns is a collection of columns and you can add stuff into it whenever you wish for.
My ObservableCollection has three items, and the rows are consistently shown in the datagrid.
I cannot turn into edit mode a single cell of my DataGrid. I tried click, click-click, double-click, F2,…, but the whole row stay selected. How can I let the user edit the datagrid.
I found similar datagrid edit-questions in other posts but no-one solved my problem. Here is the code (WPF NetFramework 4.5). Pursposely, only the first column is non-editable (readonly).
<DataGrid Name="myDataGrid" Grid.Row="2" AutoGenerateColumns="False" ItemsSource="{Binding}" IsReadOnly="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="name" IsReadOnly="True" Width="200" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Formulation" Width="100" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FormulationStr}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBlock Text="{Binding FormulationStr}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="volume Diff" Width="100" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding volumeDiff}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBlock Text="{Binding volumeDiff}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
You have placed TextBlock in cell template as well as in cell editing template. That's why you are not noticing any change on pressing F2 and double-clicking the cell since no matter what it will always be TextBlock which you can't edit.
Either placed TextBox in your CellEditingTemplate like this -
<DataGridTemplateColumn Header="Formulation" Width="100" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FormulationStr}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding FormulationStr}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
Or either simply use the DataGridTextColumn in place of DataGridTemplateColumn which internally provides the support what are you trying to achive by the above code -
<DataGridTextColumn Header="Formulation" Width="100" IsReadOnly="False" Binding="{Binding FormulationStr}" />
I want to use the DataGridevents (DataGridBeginningEdit, DataGridCellEditEnding, ..etc) to handle and detect changes. As far as I understood, without a "CellTemplate" these are not triggered. So I am trying to create an appropriate celltemplate using a TextBlock, but I guess it is not very straightforward with the binding I am using for the Combobox in the CellEditingTemplate, because I am using "DisplayMemberPath"..
There are examples of simpler cases but I couldn't find smth for this scenario. See Xaml snippet below;
<data:DataGridTemplateColumn Width="100">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Center" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding DurationTypeList, Source={StaticResource itemSourceProvider}}"
SelectedValuePath="Code"
SelectedValue="{Binding Path=DurationTypeCode, Mode=TwoWay}"
DisplayMemberPath="Template" />
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>
Thank you
It turns out, i have two options..
Solution #1
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock HorizontalAlignment="Left" Text="{Binding Path=DurationType.Template, Mode=OneWay}" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox HorizontalAlignment="Stretch"
ItemsSource="{Binding DurationTypeList, Source={StaticResource itemSourceProvider}}"
SelectedValuePath="Code"
SelectedValue="{Binding Path=DurationType, Mode=TwoWay}"
DisplayMemberPath="Template" />
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
I changed the binding path from string to the object with Code and Template properties..
This blog helped a lot..