Render custom XAML inside cells of a particular column in WPF - wpf

I have a DataGrid and I would like to have my first column's cells all render some custom XAML.
Currently I have just the grid:
<DataGrid CanUserSortColumns="False" SelectionUnit="FullRow" HeadersVisibility="Column" ItemsSource="{Binding Test}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Foo}" Header="Foo"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=Bar}" Header="Bar"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
For starters, I would like to be able to add some specific WPF control/XAML into the first column's cells.

You just need to use a DataGridTemplateColumn with a CellTemplate:
<DataGridTemplateColumn Header="Foo">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Foo}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Related

WPF Datagrid RowDetails display disable for specific column click

I'm hoping this is possible to do using XAML only.
I have a Datagrid containing 3 DataGridTextColumns and 1 DataGridComboBoxColumn, the RowDetailsTemplate display when on a single-click of any DataGridCell, the problem is it displays when I click on the DataGridComboBoxColumn, I'd like to disable the showing of the RowDetailsTemplate for this column only. I've seen solutions involving adding events to DataGrid cells and then showing/hiding the row using the code-behind file but would prefer this to be a XAML only solution if possible
<DataGrid
ItemsSource="{Binding Employees}"
Background="Transparent"
CanUserAddRows="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
SelectionUnit="FullRow"
SelectionMode="Extended"
AutoGenerateColumns="False"
HeadersVisibility="Column"
Grid.Row="1">
<DataGrid.Columns>
<DataGridTextColumn Header="Email" Binding="{Binding Email}"/>
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
<DataGridComboBoxColumn ItemsSource="{Binding Departments}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="ROW DETAILS HERE"/>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>

Bind multiple usercontrols to a datagrid row

I am trying to build a booking screen where the columns will be Monday through Sunday. There may be multiple rows but i don't think that is important. I want to add seven user controls and bind each one to a different day of the week.
I have a datagrid with a usercontrol in it and it is working. To get it working I had to bind the usercontrol to a specific property on the datarow (Mon). I want to be able to tell the usercontrol what property to bind to through xaml
The user control datagrid looks like this.
<DataGrid
IsReadOnly="False"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
SelectionMode="Extended"
ItemsSource="{Binding Mon.BookingWeekBookingList, Mode=OneWay}"
SelectionUnit="FullRow"
EnableColumnVirtualization="True"
EnableRowVirtualization="True" >
<DataGrid.Columns>
<DataGridTextColumn Header="Contract" Width="50*" IsReadOnly="True" Binding="{Binding Path=ContractId}" />
<DataGridTextColumn Header="Tonnes" Width="50*" IsReadOnly="True" Binding="{Binding Path=Tonnes}" />
</DataGrid.Columns>
</DataGrid>
On the main window I add the userControll to the datagrid like this
<DataGridTemplateColumn Header="Monday" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<local:BookingWeekIntervalView DataContext="{Binding}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
How Can I change it so I Specify the day of week in the main window binding? Rather than the itemsSource on the user control.
I was actually quite close, the answer is to set the usercontrol's databinding like so
ItemsSource="{Binding BookingWeekBookingList, Mode=OneWay}"
and then in the main window
<DataGridTemplateColumn Header="Sunday" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<local:BookingWeekIntervalView DataContext="{Binding Path=Sun}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Why datepicker not appearing in my datagrid

Why datepicker is not appearing in my datagrid.
I have textblock, one datepicker and then again textblock in total three columns, Those two textblocks appears properly but the datepicker do not appear. whereas there is no problem in binding because if a have applied same in the listview and there they are appearing, it's something wrong i have done in xaml in datagrid which i am not able to figure it out. I want user to select dates from this datepicker.
Below is my code, what i am missing any idea ?
<DataGrid AutoGenerateColumns="False"
ColumnWidth="*"
AutoGenerateColumns="False"
CanUserSortColumns="False"
ItemsSource="{Binding EquipMaintCollection}"
SelectedIndex="{Binding SelectedIndexOfItem}"
SelectedItem="{Binding SelectedMaintElement}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="{x:Static res:LocalizedString.Name}" />
<DataGridTemplateColumn Header="MainteDue">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<DatePicker x:Name="MainteDue" SelectedDate="{Binding MainteDue, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=MainteDue,Mode=TwoWay,StringFormat={}{0:dd/MM/yyyy}}" VerticalAlignment="Center" HorizontalAlignment="Left">
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Until Due" Width="*" MinWidth="100" Foreground="{Binding UntilDue, Converter={StaticResource BoolToRedBrushConverter}}" Binding="{Binding Path=UntilDue}" />
</DataGrid.Columns>
</DataGrid>

WPF DataGrid TemplateColumn not switching between edit and normal templates

I have a WPF DataGrid and I am trying to display a TextBlock when not in edit mode and a ComboBox when editing. I would think this would be easy, but it is not. I can only get it to working using a brute force method of placing the controls in a Grid and using a Visibility binding to show the controls in turn; which is a real pain.
Why does the following not work:
I can get one or the other to show, but not both based on cell editing.
<DataGrid Background="DarkGray" ItemsSource="{Binding Items}" CanUserAddRows="false" AutoGenerateColumns="False"
ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionChanged="DataGrid_SelectionChanged" SelectedIndex="{Binding SelectedIndex}"
behaviors:DataGridBehavior.OnSelectAction="{Binding Path=OnSelectionChanged}">
<DataGrid.Columns>
<DataGridTextColumn Header="Button" Binding="{Binding Button}" />
<DataGridTextColumn Header="Button Display" Binding="{Binding ButtonDisplay}" />
<DataGridTextColumn Header="Reason Code" Binding="{Binding ReasonCode}" />
<!--<DataGridTextColumn Header="Count Stamps" Binding="{Binding CountStamps}" />-->
<DataGridTemplateColumn Header="Count Stamps">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="True" SelectedValue="{Binding CountStamps}"
ItemsSource="{Binding Values}" DisplayMemberPath="Name" SelectedValuePath="Value" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CountStamps}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="*" />
</DataGrid.Columns>

Adjust cell height to image cell height within WPF DataGrid

In WPF when using a DataGrid, I have an Image and various text fields. When I select a row, the selection looks ugly because the text cell heights are the same size as each other but are different to the image which is dynamic depending on the width of the image's grid column width.
In otherwords, the blue background colour that you get upon selection is quite large on the image cell as it is for the others as I show in the image below:
The DataGrid is just being constructed right now so it is very simple. I am just not sure of the easiest, cleanest, minimal code approach (if there is such a thing with WPF!). Here is the xaml for it so far:
<DataGrid Margin="10,52,10,10" IsReadOnly="True" AutoGenerateColumns="False" Name="MainGrid" ItemsSource="{Binding CurrentData}" GridLinesVisibility="Horizontal" HorizontalGridLinesBrush="#FFBFBFBF" VerticalGridLinesBrush="White" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Image" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Picture}" RenderOptions.BitmapScalingMode="HighQuality" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="SKU" Binding="{Binding SKU}" />
...
...
<DataGridTextColumn Header="Product Name" Binding="{Binding Label}" />
</DataGrid.Columns>
</DataGrid>
So, over to the WPF gurus. I have hunted high and low and haven't found something that seems to do it.
It would appear I found the solution. It was quite simple really, as I simply used DataGridTemplateColumn for each text field and put a TextBlock inside. This resolved the selection and the selection effect filled the whole cell due to the way the TextBlock filled the available space. I used VerticalAlignment to center the text and then it looked much much better as shown below:
For completion, here is the xaml:
<DataGrid Margin="10,52,10,10" IsReadOnly="True" AutoGenerateColumns="False" Name="MainGrid" ItemsSource="{Binding CurrentData}" GridLinesVisibility="Horizontal" HorizontalGridLinesBrush="#FFBFBFBF" VerticalGridLinesBrush="White">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Image" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Picture}" RenderOptions.BitmapScalingMode="HighQuality" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="SKU" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SKU}" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
...
<DataGridTemplateColumn Header="Label" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Label}" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
There is probably a much better way using styling and what not but this worked quite nicely without any code behind. Simples!?

Resources