WPF Datagrid - Force singleline rows - c#

I'm working on a datagrid in WPF and I have encountered a problem.
When adding a multiline string to my DataGridTextColumn, the row is expanded in height so as to fit the entire text. I wish the row height to remain constant at all times, ie only show the first line.
Does anyone know a solution? Seems like a simple enough task, but I havn't been able to find anything of worth on the subject.
Here is my XAML:
<DataGrid Grid.Row="0" AutoGenerateColumns="False" HorizontalAlignment="Stretch" Name="dgPosts" VerticalAlignment="Stretch"
SelectionMode="Single" SelectionUnit="FullRow" ItemsSource="{DynamicResource LogPosts}" CanUserAddRows="False"
IsReadOnly="True" GridLinesVisibility="Vertical" RowHeaderWidth="0" Margin="0,0,0,0"
CanUserReorderColumns="True" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="True" SelectionChanged="dgPosts_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="Tidpunkt" Width="120" Binding="{Binding Path=TimeStr}"/>
<DataGridTextColumn Header="Posttyp" Width="55" Binding="{Binding Path=PostTypeStr}" CellStyle="{StaticResource CenterCellStyle}"/>
<DataGridTextColumn Header="Beskrivning" Width="*" Binding="{Binding Path=Text}"/>
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="{Binding Path=Color}"/>
<Style.Triggers>
<Trigger Property="DataGridRow.IsSelected" Value="True" >
<Setter Property="Background" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0"/>
</Style>
</DataGrid.CellStyle>
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
</DataGrid.Resources>
</DataGrid>
Thanks in advance!

You just have to set a Row Height in the DataGrid:
<DataGrid RowHeight="50">
</DataGrid>
And that's it.

Related

DataGrid Textbox DataTrigger Condition Not Working As Expected

I have a window that has datagrid populated from datasource. I'm using DataGridTemplateColumn and has textbox. I want to make this textbox read only based on my DrawingType property value. Let's say I have this editable textbox from "Line From X" column. This is only editable if the DrawingType is "Line". My datatrigger condition works fine on window load. However I have issue on new item added on the grid. When I select Ellipse from DrawingType combobox, the textbox "Line From X" should be read only. However I can still input some texts. But when I leave the focus cursor let's say focus to other cells, it's now the time that the newly added item "Line From X" becomes read only. Please help. Here's what I want to achieve.
Make the target textboxes read only whether data came from datasource or newly added. The read only must be evaluated immediately during selection of DrawingType property. I'm using DataTrigger but if other approach can be done, that's okay.
Make the style generic since I'll be applying it to 2 or more columns. I'll convert other columns to DataGridTemplateColumn and add textboxes too using the same datatrigger.
Here's my code and screenshots.
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
</Grid.RowDefinitions>
<DataGrid ItemsSource="{Binding DrawnObjects}" AutoGenerateColumns="False" Grid.Row="0" Margin="0,20" Name="dgBldgDrawings" CanUserAddRows="False" IsEnabled="{Binding IsManuallyAdded,Converter={StaticResource VisibilityConverter}}">
<DataGrid.Columns>
<DataGridComboBoxColumn ItemsSource="{x:Static ext:Extensions.GetEnumTypes}" SelectedItemBinding="{Binding DrawingType}" Width="85" Header="Drawing Type">
<DataGridComboBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding IsManuallyAdded}" Value="False">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridComboBoxColumn.CellStyle>
</DataGridComboBoxColumn>
<DataGridTextColumn Width="60" Header="X" Binding="{Binding Path=FootX}"/>
<DataGridTextColumn Width="65" Header="Y" Binding="{Binding Path=FootY}"/>
<DataGridTextColumn Width="65" Header="Width" Binding="{Binding Path=FootWidth}"/>
<DataGridTextColumn Width="65" Header="Height" Binding="{Binding Path=FootHeight}"/>
<DataGridTextColumn Width="65" Header="Text" Binding="{Binding Path=Text}"/>
<DataGridTemplateColumn Width="80" Header="Line From X">
<DataGridTemplateColumn.CellTemplate >
<DataTemplate >
<TextBox Text="{Binding LineFootX1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="16">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DrawingType,UpdateSourceTrigger=PropertyChanged}" Value="Line">
<Setter Property="IsReadOnly" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="80" Header="Line From Y" Binding="{Binding Path=LineFootY1}"/>
<DataGridTextColumn Width="70" Header="Line To X" Binding="{Binding Path=LineFootX2}"/>
<DataGridTextColumn Width="70" Header="Line To Y" Binding="{Binding Path=LineFootY2}"/>
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Visibility" Value="{Binding IsForManualDraw, Converter={StaticResource VisibilityConverter}}"/>
</Style>
</DataGrid.RowStyle>
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
</DataGrid.Resources>
</DataGrid>
<Button Content="Add New Drawing" Width="150" Command="{Binding AddNewDrawingCommand}" Height="25" Grid.Row="1" Margin="0,0,250,0"/>
<Button Content="Save" Width="75" Command="{Binding SaveDrawingChangesCommand}" Height="25" Grid.Row="1"/>
</Grid>
Screenshots:
Add another DataTrigger to work if the row is newly added. Based on your posted code it seems that IsManuallyAdded property represents if a new row is added during session.
<Style TargetType="TextBox">
<Setter Property="IsReadOnly" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DrawingType,UpdateSourceTrigger=PropertyChanged}" Value="Line">
<Setter Property="IsReadOnly" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding IsManuallyAdded}" Value="True">
<Setter Property="IsReadOnly" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
Or you can bind it to IsManuallyAdded as shown below:
<Style TargetType="TextBox">
<Setter Property="IsReadOnly" Value="{Binding IsManuallyAdded}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DrawingType,UpdateSourceTrigger=PropertyChanged}" Value="Line">
<Setter Property="IsReadOnly" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
For #2, you can take the style and defined in the resources with the key like <Style TargetType="TextBox" x:Key="MyKey"> and later can apply this on Textbox like
<TextBox Style={StaticResource MyKey} ..... />

How to set grid lines in a one pixel width (WPF DataGrid)?

I am using the WPF datagrid to display some data and I want to grid lines thickness was equal to one pixel, but each cell displays unwanted border. How to get rid of it and set thickness of all lines to one pixel (like in DataGridView in WinForms)?
XAML:
<DataGrid HeadersVisibility="Column" SelectionUnit="Cell">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
<DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
</DataGrid.Columns>
</DataGrid>
Result:
This is the solution!
Settig parameter RenderOptions.EdgeMode="Aliased"
Many thanks to David Kossoglyad for this solution.
<DataGrid RenderOptions.EdgeMode="Aliased" UseLayoutRounding="True" ....>
This might do the trick for you
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="1,0,0,1"/>
<Setter Property="BorderBrush" Value="Black"/>
</Style>
</DataGrid.CellStyle>
Try this:
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="1" Opacity="0" ShadowDepth="0"/>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
If this wouldn't help try to set same property for DataGrid.RowStyle.

How to make DataGrid a single stop as a whole on focus traversal with arrow keys row selection?

I have a Window with few controls on it. One of them is a DataGrid. I want to implement some non-default focus traversal. Namely:
DataGrid is a single stop as a whole, not each row.
When DataGrid is focused, user can navigate through rows using up and down keys.
Navigating through columns using left and right keys is not allowed.
First column (and the only relevant for navigation) is of type DataGridHyperlinkColumn. When user hits Space or Enter key, it executes the hyperlink.
At the moment I have the following code:
<DataGrid x:Name="DocumentTemplatesGrid"
Grid.Row="2"
ItemsSource="{Binding Source={StaticResource DocumentTemplatesView}}"
IsReadOnly="True"
AutoGenerateColumns="False"
SelectionUnit="FullRow"
SelectionMode="Single"
TabIndex="1"
IsTabStop="True">
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsTabStop" Value="False"/>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="IsTabStop" Value="False"/>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridHyperlinkColumn Header="Name"
Width="2*"
Binding="{Binding Name}"/>
<DataGridTextColumn Header="Description"
Width="5*"
Binding="{Binding Description}"/>
<DataGridTextColumn Header="Type"
Width="*"
Binding="{Binding Type}"/>
</DataGrid.Columns>
</DataGrid>
Unfortunately, it does not reach my expectations.
Could you, please, explain how to achieve this?
So, my suggestion to you is this:
<DataGrid x:Name="DocumentTemplatesGrid"
Grid.Row="2"
ItemsSource="{Binding Items}"
IsReadOnly="True"
AutoGenerateColumns="False"
SelectionMode="Single"
SelectionUnit="FullRow"
TabIndex="1"
IsTabStop="True"
PreviewKeyDown="DocumentTemplatesGrid_PreviewKeyDown">
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="IsTabStop" Value="False"/>
</Style>
</DataGrid.RowStyle>
I have added the PreviewKeyDown event on the DataGrid, and I have removed the cell selection from each cell. As a result, it will seem like selection is on row only.
In the code behind, this is what opens the links with Space / Enter:
private void DocumentTemplatesGrid_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Space || e.Key == System.Windows.Input.Key.Enter)
{
if (e.Source is DataGrid)
{
string navigationUri = ((e.Source as DataGrid).SelectedItem as Class).Name;
Process.Start(navigationUri);
}
e.Handled = true;
}
}
Hope this is what you are looking for, or atleast of some help.

How to change color of DataGrid Cell when empty

I have a Datagrid, I want to change the color of the cells when they are empty.
This works, however I want to place the style outside the Datagrid.
However I don't know how to achieve this.
So far I have:
<Grid>
<Grid.Resources>
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Text" Value="">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
</Grid.Resources>
<DataGrid Name="Table1" ItemsSource="{Binding Items}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}">
</DataGridTextColumn>
<DataGridTextColumn Header="Number" Binding="{Binding Number}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
But this doesn't work. What is the correct way to set this style?

Binding to dataGrid SelectedItem

I have DataGrid like this:
<DataGrid AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" GridLinesVisibility="None">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderThickness="{Binding ???}" BorderBrush="Black" >
<Grid></Grid>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid>
And I need to bind BorderThickness of Border in CellTemplate to DataGrid.SelectedItem. For example: if cell is in selected row thickness must be 1,1,1,1 else zero. (I know about converters). How to do this?
Can be achieved using triggers:
<DataGrid AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" GridLinesVisibility="None">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="Black" >
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridCell}}" Value="True">
<Setter Property="BorderThickness" Value="1"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid></Grid>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
OR
Directly set CellStyle like
<DataGrid AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" GridLinesVisibility="None">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="BorderBrush" Value="Black"></Setter>
</Trigger>
</Style.Triggers>
</Style>
Converters may not be the way to go with this, try using a datatrigger on the selected grid item which changes the border style, have a gander at this http://www.wpf-tutorial.com/styles/trigger-datatrigger-event-trigger/

Categories