Combobox in a cell of DataGrid - c#

I have a database with Table name “tblProducts” with columns header “ProductCode, Descriptions, UnitPirce, Quantity, TotalPrice”
I have a DataGrid in my WPF form, and manually create the column headers as below:
<DataGrid x:Name="dataGridOrderedProducts" Margin="10,10,10,0" Grid.Row="3" Grid.ColumnSpan="4" VerticalAlignment="Center" Height="180" BorderThickness="1">
<DataGrid.Columns>
<DataGridTextColumn Header="Product Code" MinWidth="120" FontSize="11"/>
<DataGridTextColumn Header="Descriptions" MinWidth="200" FontSize="11"/>
<DataGridTextColumn Header="Unit Price" MinWidth="100" FontSize="11"/>
<DataGridTextColumn Header="Quantity" MinWidth="100" FontSize="11"/>
<DataGridTextColumn Header="Total Price" MinWidth="100" FontSize="11"/>
</DataGrid.Columns>
</DataGrid>
I want to have a ComboBox in a cell under “Product Code” columns so that users can select a product and query all the related data from that ProductCode.
How can I do that?

You can do this in two- ways,
(i).By using DataGridComboboxColom
<DataGridComboBoxColumn Width="100" x:Name="cmbProduct" SelectedValueBinding="{Binding Code, Mode=TwoWay}" DisplayMemberPath="{Binding Code}"></DataGridComboBoxColumn>
</DataGrid.Columns>
(ii)By using DataTemplate
<DataGridTemplateColumn Header="ProductCode">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Code}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Codes}"></ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Related

WPF DataGrid repeat Headers in all rows

My requirement is to display headers of DataGrid in following format instead of normal grid.
My code for normal DataGrid as follows:
<DataGrid Margin="7.208,8,7.888,8" Grid.Row="2" AutoGenerateColumns="False" Name="gridOrder" BorderBrush="#FFB38807" Background="#FFEDEDEC" HorizontalGridLinesBrush="#FFB38807" VerticalGridLinesBrush="#FFB38807" SelectionChanged="gridOrder_SelectionChanged" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Order ID" Binding="{Binding orderid}" />
<DataGridTextColumn Header=" Order Time" Binding="{Binding orderTime}" />
<DataGridTextColumn Header="Order Status" Binding="{Binding orderStatus}" />
</DataGrid.Columns>
</DataGrid>
Can any one help me out for this kind of requirement.
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="OrderId : "/>
<TextBlock Text="{Binding OrderId}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="OrderTime : "/>
<TextBlock Text="{Binding OrderTime}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="OrderStatus : "/>
<TextBlock Text="{Binding OrderStatus}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

MVVM WPF properties

In my WPF project a DataGrid is bound to a collection. When DataGrid row selection changes the corresponding TextBox, should get updated. The DataGrid selected item is bound to a property
SelectedItem="{Binding CardType.SelectedCard}"
and corresponding Text box is bound
Text="{Binding CardType.SelectedCard.LimitBalance}"
so when a selected item is changed, my text box will get updated.
DataGrid
<DataGrid
x:Name="dtGridSearch"
Margin="0,0,8,0"
AutoGenerateColumns="False"
GridLinesVisibility="None"
SelectionMode="Single"
CanUserAddRows="False"
BorderThickness="0"
RowHeaderWidth="0"
RowStyle="{StaticResource TCAS_RowStyle}"
ItemsSource="{Binding CardType.Cards}"
SelectedItem="{Binding CardType.SelectedCard}"
SelectionChanged="dtGridSearchSelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn x:Name="CardCode" Binding="{Binding CardId}" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}" IsReadOnly="True" Width="150" CanUserResize="False" >
<DataGridTextColumn.Header>
<TextBlock x:Name="tbCardCode" Text=""/>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn x:Name="CardName" Binding="{Binding CardDescription}" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}" IsReadOnly="True" Width="250" CanUserResize="False" >
<DataGridTextColumn.Header>
<TextBlock x:Name="tbCardName" Text="" HorizontalAlignment="Center"/>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn x:Name="ProductCode" Binding="{Binding ProductTypeCode}" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}" IsReadOnly="True" Width="150" CanUserResize="False" >
<DataGridTextColumn.Header>
<TextBlock x:Name="tbProductCode" Text=""/>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn x:Name="Limitbalance" Binding="{Binding LimitBalance}" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}" IsReadOnly="True" Width="100*" CanUserResize="False" >
<DataGridTextColumn.Header>
<TextBlock x:Name="tbLimitbalance" Text="" HorizontalAlignment="Center"/>
</DataGridTextColumn.Header>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
TextBox
<TextBox
x:Name="txtLimitbalance"
Grid.Row="3"
Grid.Column="1"
Margin="16,0,0,0"
Style="{StaticResource TMS_TextBox_Base1}"
Text="{Binding CardType.SelectedCard.LimitBalance, Mode=TwoWay}"
MaxLength="45"
Height="24"
Width="210"
TabIndex="4"
PreviewKeyDown="txtLimitbalancePreviewKeyDown"/>
<CheckBox
x:Name="chkused"
Grid.Row="3"
Grid.Column="2"
Margin="16,4,0,8"
Content="{Binding Resources.NPUsed}"
IsChecked="{Binding CardType.SelectedCard.ActiveStatus, Mode=TwoWay}"
TabIndex="5"/>
User update the text box to a different value from original value , so one property of row1 is updated ,now user selected the different row i.e rowenter code here2 from datagrid. again user selected the row1 so it is dispalying updated value not original value. I want to display original value only.

How to provide an option to edit the record on Mouse right click in datagrid in WPF

I have datagrid in WPF c#. I need to provide some facility in datagrid so that if user right clicks on any row/column then some interface(like menu) should be displayed.
That interface will have two options.
1. ADD NEW RECORDS.
2. EDIT CURRENT RECORDS.
If user will click on any of the section, which event will be fired to handle this request.
Below is my datagrid.
<DataGrid IsReadOnly="True" Name="dgShowSearching" Sorting="dgShowSearching_Sorting" FrozenColumnCount="7" AutoGenerateColumns="False" HorizontalAlignment="Center" VerticalAlignment="Stretch">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontWeight"
Value="Bold" />
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="LightBlue" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Visibility="Collapsed" Header="KeywordD" Width="120" Binding="{Binding KeywordID}"/>
<DataGridTemplateColumn Header="Edit Filter" Width="80">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Click="btnEditRecords_Click" Name="btnEditRecords" Content="Edit"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Import Records" Width="90">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Click="Import_Click" Name="btnImportRecords" Content="Import"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Records To Import" Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox IsReadOnly="False" Width="120" Text="{Binding Path=RecordsToImport, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Right" HorizontalAlignment="Right" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=RecordsToImport, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Priority">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cbPriority"
Width="60"
Height="22"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
SelectedItem="{Binding SelectedPriority, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,FallbackValue=1}">
<sys:Int32 >1</sys:Int32>
<sys:Int32>2</sys:Int32>
<sys:Int32>3</sys:Int32>
<sys:Int32>4</sys:Int32>
<sys:Int32>5</sys:Int32>
<sys:Int32>6</sys:Int32>
<sys:Int32>7</sys:Int32>
<sys:Int32>8</sys:Int32>
<sys:Int32>9</sys:Int32>
<sys:Int32>10</sys:Int32>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=SelectedPriority, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Total Records" Width="100" SortMemberPath="TotalRecords" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=TotalRecords}" Width="{Binding ActualWidth,ElementName=TotalRecords}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Records Imported" Width="100" SortMemberPath="TotalRecordsImported">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=TotalRecordsImported}" Width="{Binding ActualWidth,ElementName=TotalRecordsImported}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Status" Width="120" Binding="{Binding Status}"/>
<DataGridTextColumn Header="First Name" Width="120" Binding="{Binding FirstName}"/>
<DataGridTextColumn Header="Last Name" Width="120" Binding="{Binding LastName}"/>
<DataGridTextColumn Header="All Words" Width="120" Binding="{Binding WithAllOfTheWords}"/>
<DataGridTextColumn Header="Exact Phrase" Width="120" Binding="{Binding WithTheExactPhrase}"/>
<DataGridTextColumn Header="At Least One Word" Width="120" Binding="{Binding WithAtLeastOneOfTheseWords}"/>
<DataGridTextColumn Header="Without Word" Width="120" Binding="{Binding WithoutTheWord}"/>
<DataGridTemplateColumn Header="Exact Date" Width="120" SortMemberPath="ExactDate">
<DataGridTemplateColumn.CellTemplate >
<DataTemplate>
<TextBlock Text="{Binding Path=ExactDate, StringFormat='MM/dd/yyyy'}" Width="{Binding ActualWidth,ElementName=ExactDate}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Start Date" Width="120" SortMemberPath="StartDate" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=StartDate, StringFormat='MM/dd/yyyy'}" Width="{Binding ActualWidth,ElementName=StartDate}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="End Date" Width="120" SortMemberPath="EndDate">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=EndDate, StringFormat='MM/dd/yyyy'}" Width="{Binding ActualWidth,ElementName=EndDate}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate >
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Start Year" Width="120" SortMemberPath="StartYears" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=StartYears}" Width="{Binding ActualWidth,ElementName=StartYears}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="End Year" Width="120" SortMemberPath="EndYear" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=EndYear}" Width="{Binding ActualWidth,ElementName=EndYear}" TextAlignment="Right" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Country" Width="120" Binding="{Binding CountryName}"/>
<DataGridTextColumn Header="State" Width="120" Binding="{Binding StateName}"/>
<DataGridTextColumn Header="City" Width="120" Binding="{Binding CityName}"/>
<DataGridTextColumn Header="Publication" Width="120" Binding="{Binding PublicationName}"/>
</DataGrid.Columns>
</DataGrid>

WPF Dataset DataGrid Foreign Key Binding

I have two tables in a dataset:
Schedules
-------------
id INT
schedule_date DATETIME
service_id INT FOREIGN KEY REFERENCES services(id)
Services
-------------
id INT
name VARCHAR
I can easily bind a DataGridComboBoxColumn and get the result I want in the following way:
<DataGridComboBoxColumn Header="Service"
ItemsSource="{Binding Source={StaticResource schedulesDataSet}, Path=services}"
DisplayMemberPath="name"
SelectedValueBinding="{Binding Path=service_id}"
SelectedValuePath="id" />
But how do I do it with a DataGridTemplateColumn? I want to do this:
<DataGridTemplateColumn Header="Service" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=services.name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
But as I am using a Dataset and not Entity Framework, I guess that's why it doesn't work.
What's the right way to do it?
EDIT:
Complete DataGrid code:
<Grid DataContext="{Binding Source={StaticResource schedulesViewSource}}">
<DataGrid Margin="0,10,0,0" Grid.Row="1" ItemsSource="{Binding}" AutoGenerateColumns="False" CanUserResizeRows="False" Name="schedulesDataGrid">
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding Path=schedule_date,StringFormat=dd-MMM-yy,ConverterCulture=da-DK}" Width="*" />
<DataGridTemplateColumn Header="Service" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=services.name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridComboBoxColumn Header="Status" Width="*" x:Name="scheduleStatusColumn" ItemsSource="{StaticResource ScheduleStatuses}" />
<DataGridTextColumn Header="Source" Binding="{Binding Path=done_by}" Width="*" />
</DataGrid.Columns>
</DataGrid>
</Grid>
Set the ItemsSource for your DataGrid
<DataGrid Margin="0,10,0,0" Grid.Row="1" ItemsSource="{Binding schedulesViewSource, Mode=OneWay}" AutoGenerateColumns="False" CanUserResizeRows="False" Name="schedulesDataGrid">

WPF Custom datagrid column header

I need to create a Custom dataGrid DataGridTextColumn like the sketch below:
The Red rectangles are TextBox and are used to search within the column.
so far i have implemented a datagrid like this (simplify Version):
<DataGrid x:Name="CompassLogDataGrid"
Grid.Row="1"
Style="{DynamicResource ResourceKey=DataGridStyle}"
IsTextSearchEnabled="True">
<DataGrid.Columns>
<DataGridTextColumn CellStyle="{StaticResource IdCell}"
x:Name="ID"
Header="ID"
Foreground="Black"
Binding="{Binding ID}"
DisplayIndex="0" />
<DataGridTextColumn x:Name="DateGTC"
Header="Date"
Binding="{Binding DateString}"
CellStyle="{StaticResource DateGTCCell}" />
</DataGrid.Columns
</DataGrid
I have no idea how to create those textBoxes. Any clue would be appreciate it
DataGridTemplateColumn is what you are looking for. You can customize the template as per your need -
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox BorderBrush="Red" BorderThickness="3" Margin="5"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
With sample ItemsSource it gives this look -
EDIT
In case you want to customize the header, you need to provide HeaderTemplate for your column like this -
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"
Header="{Binding HeaderName}">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Content, RelativeSource=
{RelativeSource Mode=TemplatedParent}}"
Margin="5"/>
<TextBox BorderBrush="Red" BorderThickness="3"
Width="50" Margin="5"/>
</StackPanel>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
Here's the look -

Categories

Resources