Binding to dataGrid SelectedItem - c#

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/

Related

How to change background of the template item, on selecting DataGridCell

I need to change the background color of a Textbox that is inside DataGridTemplateColumn cell based on whether or not if the data cell is selected.
Currently what I managed to do is, changing the background color of the template cell, which became useless because of error management.
Thus, I want to change the background of the Textbox, and revert it back on selection changed.
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="DarkBlue"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn IsReadOnly="True" MinWidth="150" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=TwoDLineName, Mode=TwoWay,UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
HorizontalAlignment="Stretch" Style="{StaticResource TextBoxValidated}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
You could use a Style with a DataTrigger that binds to the IsSelected property of the parent row:
<DataGridTemplateColumn IsReadOnly="True" MinWidth="150" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=TwoDLineName, Mode=TwoWay,UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True, NotifyOnValidationError=True}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxValidated}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=DataGridRow}}"
Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

WPF DataGrid trigger on other cell value

I have DataGrid:
<DataGrid x:Name="PART_DataGrid"
ItemsSource="{TemplateBinding Items}"
AutoGenerateColumns="False"
Margin="2,25,2,2">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Language" Width="SizeToCells" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding Path=Language, Mode=OneWay}"
ItemsSource="{Binding LanguagesSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
FontSize="16"
IsEnabled="False">
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=test }" Value="">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Translation" Width="SizeToCells" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="TranslationValueTB"
Text="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged}"
BorderThickness="0"
FontSize="16" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
And I want to set that first column ComboBox will be enabled when second TextBox.Text is empty, I have tried different binding methods but none of them have worked. So how can I do that?
Bind to the Value source property that the TextBox in the second column is bound to:
<DataGridTemplateColumn Header="Language" Width="SizeToCells" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding Path=Language, Mode=OneWay}"
ItemsSource="{Binding LanguagesSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
FontSize="16"
IsEnabled="False">
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<DataTrigger Binding="{Binding Value}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding Value}" Value="">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Also make sure that the class where the Value property is defined implements the INotifyPropertyChanged interface and raises the PropertyChanged event in the setter of the Value property.
Remove the IsEnabled = false from combobox and do the same in the setter as follows, and do the binding as like follows,
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=Item.Name }" Value="{x:Static sys:String.Empty}">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
Item.Name - > this is the property you need to check

WPF DataGridCell Margin

I have the following data grid:
<DataGrid Name="PropertiesDataGrid"
ItemsSource="{Binding PropertiesDataView, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedProperty, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False"
CanUserAddRows="False"
MaxHeight="200">
<i:Interaction.Behaviors>
<helper:ScrollIntoViewBehavior/>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTemplateColumn Header="">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="Delete"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Image Source="../Resources/red_x.ico"
Height="15" />
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="ID"
Width="50"
Binding="{Binding ID}"
ElementStyle="{StaticResource CenterTextCellStyle}"
IsReadOnly="True" />
<DataGridTextColumn Header="PropertyName"
Width="*"
Binding="{Binding PropertyName}"
ElementStyle="{StaticResource LeftTextCellStyle}" />
<DataGridTextColumn Header="PropertyValue"
Width="300"
Binding="{Binding PropertyValue}"
ElementStyle="{StaticResource LeftTextCellStyle}" />
</DataGrid.Columns>
</DataGrid>
Applied to this data grid is the following style:
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Height" Value="22" />
<Setter Property="Margin" Value="5,0,0,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This style adds 5 pixels of spacing to the left of the cell contents and centers the text vertically.
I would like to set the margin of just the first column's cells (<DataGridTemplateColumn Header="">) to 0. How can I set this in the DataTemplate. I know the Margin has to be set on DataGridCell (found by using Snoops) but do not know how to implement in the <DataGridTemplateColumn.CellTemplate>
Cascade the style:
<DataGridTemplateColumn Header="">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Margin" Value="0" />
</Style>
</DataGridTemplateColumn.CellStyle>

WPF Datagrid - Force singleline rows

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.

How to make mutually Exclusive checkBoxes in WPF DataGrid Columns

I am having following DataGrid Code
<UserControl x:Class="abc.WPFApp.UCGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPFtoolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:local="clr-namespace:abc.WPFApp">
<UserControl.Resources>
<!--Restrict editing based on IsVariable-->
<Style x:Key="CheckBoxCellStyle" TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsVariable}" Value="true">
<Setter Property="IsEnabled" Value="false"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</UserControl.Resources>
<Grid>
<WPFtoolkit:DataGrid x:Name="UCdataGridView" ItemsSource="{Binding}"
CellStyle="{StaticResource defaultCellStyle}"
RowStyle="{StaticResource defaultRowStyle}"
ColumnHeaderStyle="{StaticResource defaultDataGridColumnHeader}"
SelectionUnit="FullRow"
IsSynchronizedWithCurrentItem="True"
RowBackground="White"
AlternatingRowBackground="AliceBlue"
AutoGenerateColumns="False" SelectionMode="Extended" RowHeaderWidth="20"
CanUserAddRows="True" CanUserDeleteRows="True" CanUserReorderColumns="False"
CanUserResizeColumns="True" AllowDrop="True" KeyUp="UCGridKeyUp" >
<WPFtoolkit:DataGrid.Columns>
<WPFtoolkit:DataGridCheckBoxColumn x:Name="dgChkRepeatingData" Binding="{Binding Path=MasterDataFlag}" MaxWidth="135" MinWidth="80"
Header="Repeating data" Visibility="Collapsed" IsReadOnly="{Binding (IsVariable)}"
EditingElementStyle="{StaticResource CheckBoxCellStyle}"
>
</WPFtoolkit:DataGridCheckBoxColumn>
<WPFtoolkit:DataGridCheckBoxColumn MaxWidth="100" Header="Max Element" x:Name="dgChkMaxElement"
Binding="{Binding Path=MaxElement}" MinWidth="70" Visibility="Collapsed"
EditingElementStyle="{StaticResource CheckBoxCellStyle}">
</WPFtoolkit:DataGridCheckBoxColumn>
<WPFtoolkit:DataGridCheckBoxColumn MaxWidth="100" Header="In For Loop" x:Name="dgChkInForLoop"
Binding="{Binding Path=InForLoop}" MinWidth="70" Visibility="Collapsed"
EditingElementStyle="{StaticResource CheckBoxCellStyle}">
</WPFtoolkit:DataGridCheckBoxColumn>
<WPFtoolkit:DataGridTextColumn x:Name="dgXPath" Binding="{Binding Path=XPath}" Header="XPath" Width="500"
Visibility="Collapsed" IsReadOnly="{Binding Path=IsVariable}"
EditingElementStyle="{StaticResource TextBoxCellStyle}"/>
</WPFtoolkit:DataGrid.Columns>
</WPFtoolkit:DataGrid>
This user control Grid comprised if three Columns which should be mutually exclusive.
I want to achieve this by creating Triggers in XAML itself , How can we do this ?
You can use radiobuttons with a checkbox style to achieve mutually exclusive behavior. If you have any problem binding radiobuttons: radiobutton-binding
<RadioButton IsChecked="{Binding VMProperty}" GroupName="IsSelectedGroup">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=RadioButton}}" Content="{TemplateBinding Content}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
But, i agree with Jaster. If you have each row binded to a ViewModel, the place to put this logic restriction is the ViewModel.
i am trying by creating such Style for 3rd column "InFor" But it is not at all working
<Style x:Key="mutualCheckInForLoop" TargetType="{x:Type WPFtoolkit:DataGridCell}" BasedOn="{StaticResource {x:Type WPFtoolkit:DataGridCell}}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=dgChkRepeatingData,Path=IsChecked}" Value="True">
<Setter Property="CheckBox.IsChecked" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=dgChkMaxElement,Path=IsChecked}" Value="True">
<Setter Property="CheckBox.IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>

Categories