EditingElementStyle in a DataGridTextColumn - c#

I need to be able to distinguish from which column in a DataGrid, a TextBox has been edited:
<DataGridTextColumn Header="No" Binding="{Binding NumberOfItems}">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}" x:Name="NumOfItems">
<Setter Property="MaxLength" Value="2"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Role" Binding="{Binding Role}" Width="0.75*">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}" x:Name="Role">
<Setter Property="MaxLength" Value="30"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
so that I can update a database with the correct information. I have tried to use x:Name but, with the code below, the name is always empty
private void dgItems_CellEditEnding(object sender,
DataGridCellEditEndingEventArgs e)
{
if(e.EditingElement is TextBox)
{
TextBox t = e.EditingElement as TextBox;
..........
if (t.Name == "Role")
//do this
else if (t.NumOfItems)
//do this
}
Thanks for any help

You could set the Tag property in the Style:
<Style TargetType="{x:Type TextBox}">
<Setter Property="MaxLength" Value="30"/>
<Setter Property="Tag" Value="Role"/>
</Style>
if (t.Tag?.ToString() == "Role")

Related

wrong show text when selected item datagrid wpf

i use this code
txt_f1.Text = datagrid_customer.SelectedCells[1].Column.GetCellContent(datagrid_customer.SelectedItem).ToString();
but when i click any item
show me:
System.windows.controls.textblock
datagrid code
<DataGrid HorizontalAlignment="Left" Height="100" Margin="861,-30,-261,0"
VerticalAlignment="Top" Width="100" Name="datagrid_customer"
SelectionChanged="datagrid_customer_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="کد محصول" Binding="{Binding MahID}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="FontFamily" Value="B Yekan" />
<Setter Property="FontSize" Value="12" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
If you need to get MahID, you should be able to get it from the SelectedItem itself. Like,
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var grid = sender as DataGrid;
var mahId = (grid.SelectedItem as YourModel).MahID;
}

WPF create combo box programmatically

I'm trying to create DatagridComboBoxColumn from code behind. How can I link it to ElementStyle and EditingElementStyle?
I'm trying to create this:
<DataGridComboBoxColumn Width="*" ElementStyle="{StaticResource ComboBoxElementStyle}" EditingElementStyle="{StaticResource ComboBoxEditingElementStyle}" />
which creates this:
from this:
private DataGridComboBoxColumn CreateComboValueColumn()
{
DataGridComboBoxColumn column = new DataGridComboBoxColumn();
column.ElementStyle = ???;
column.EditingElementStyle = ???;
return column;
}
Which do not display comboBox:
Style which I'm trying to link:
<!-- ComboBox element and editing style -->
<Style x:Key="ComboBoxElementStyle" TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding ComboItems}"/>
<Setter Property="SelectedValue" Value="{Binding Value}" />
<Setter Property="DisplayMemberPath" Value="Text"/>
<Setter Property="SelectedValuePath" Value="ID" />
</Style>
<Style x:Key="ComboBoxEditingElementStyle" TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding ComboItems}"/>
<Setter Property="SelectedValue" Value="{Binding Value}" />
<Setter Property="DisplayMemberPath" Value="Text"/>
<Setter Property="SelectedValuePath" Value="ID" />
</Style>
Hello try something like this:
private DataGridComboBoxColumn CreateComboValueColumn()
{
DataGridComboBoxColumn column = new DataGridComboBoxColumn();
column.ElementStyle = YourWindowName.FindResource("ComboBoxElementStyle") as Style;
column.EditingElementStyle = YourWindowName.FindResource("ComboBoxEditingElementStyle") as Style;
return column;
}
Try something like(Style)FindResource("StyleOne")
Have a look here:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/resources-and-code

XAML trigger not triggering

do you see anything wrong with this trigger?
<Border Margin="2" BorderBrush="#6593CF" BorderThickness="1.5" >
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsCreating, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Border.BorderBrush" Value="Lime"/>
<Setter Property="Border.BorderThickness" Value="3" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
It is bound to this property:
private bool _IsCreating = false;
public bool IsCreating
{
get
{
return _IsCreating;
}
set
{
if (_IsCreating == value)
{
return;
}
_IsCreating = value;
RaisePropertyChanged("IsCreating");
}
}
When I set IsCreating = true, the style does not update.
You have set BorderBrush and BorderThinkness inline on your border. Inline declaration has quite hight precedence and override your trigger. Remove your inline declaration from border and move it to trigger:
<Border Margin="2">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=DataContext.IsCreating, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Value="true">
<Setter Property="BorderBrush" Value="Lime" />
<Setter Property="BorderThickness" Value="3" />
</DataTrigger>
<DataTrigger
Binding="{Binding Path=DataContext.IsCreating, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Value="false">
<Setter Property="BorderBrush" Value="#6593CF" />
<Setter Property="BorderThickness" Value="1.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<CheckBox IsChecked="{Binding IsCreating}" />
</Border>

How to change background color for some cell in WPF DataGrid?

I have a datagrid binded to an object collection.
One property of the objects is a string that store a color value.
On this "COLORBACKGROUND" cell click, a colorpicker opens to change it.
What I need is to change the background color of the cell by the value displayed in datagrid rows (#RGB).
<DataGrid SelectionUnit="Cell" SelectedCellsChanged="DgDataTable_OnSelectedCellsChanged" x:Name="DgDataTable" Grid.Row="0" Grid.ColumnSpan="2" Margin="10,20,10,0" AutoGenerateColumns="true" HeadersVisibility="All" RowHeaderWidth="20" Style="{StaticResource AzureDataGrid}" GridLinesVisibility="Horizontal" LoadingRow="dgDataTable_LoadingRow" ColumnHeaderHeight="10" AlternatingRowBackground="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}" AutoGeneratingColumn="DgDataTable_AutoGeneratingColumn">
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Background" Value="LightCyan"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.RowHeaderStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
<!-- <Style.Triggers>
<Trigger Property="Text" Value="John">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers> -->
</Style>
</DataGrid.CellStyle>
</DataGrid>
I tried something with AutoGenerating column :
private void DgDataTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName == "SrcAlert")
{
DataGridComboBoxColumn cb = new DataGridComboBoxColumn();
e.Column = cb;
cb.ItemsSource = new List<string> {"1", "2"};
cb.SelectedValueBinding = new Binding("SrcAlert");
e.Column.Header = "SrcAlert";
}
if (e.PropertyName.Equals("ColorBackground"))
{
DataGridTextColumn tc = new DataGridTextColumn();
e.Column = tc;
tc.Foreground = (Color)ColorConverter.ConvertFromString(DgDataTable.CurrentCell.Item.ColorBackground);
}
}
this Item.ColorBackground doesn't compile... I put it for my explanation, thats what I need.
I tried another solution I found :
if (e.PropertyName.Equals("ColorBackground"))
{
string s = DgDataTable.CurrentCell.Item.ToString();
e.Column.CellStyle.Setters.Add(new Setter(DataGridCell.BackgroundProperty, (Color)ColorConverter.ConvertFromString(s)));
}
but that was a fail.
Thank you for your help !
Edit : A screenshot of ASh solution that works perfectly for me:
EDIT : I adapted your solution for multiple columns with color Picker :
I add style setters to display only colors in the cells :
<Style TargetType="DataGridCell" x:Key="ColorPickerCellBG"
BasedOn="{StaticResource CommonCell}">
<Setter Property="Background" Value="{Binding Path=BG}"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Width" Value="30"></Setter>
</Style>
<Style TargetType="DataGridCell" x:Key="ColorPickerCellAL"
BasedOn="{StaticResource CommonCell}">
<Setter Property="Background" Value="{Binding Path=AL}"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Width" Value="30"></Setter>
</Style>
<Style...
When the cell is clicked, the rgb color value is visible, the style must be "ClickedCell"...
How can I Improve that ?
it is possible to apply special style to a single auto-generated column.
declare two cell styles in resources
<Window.Resources>
<Style TargetType="DataGridCell" x:Key="CommonCell"
BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
<Style TargetType="DataGridCell" x:Key="ColorPickerCell"
BasedOn="{StaticResource CommonCell}">
<Setter Property="Background" Value="{Binding Path=ColorBackground}"/>
</Style>
</Window.Resources>
ColorPickerCell inherits CommonCell style.
<DataGrid SelectionUnit="Cell"
x:Name="DgDataTable"
AutoGenerateColumns="true" HeadersVisibility="All" RowHeaderWidth="20"
GridLinesVisibility="Horizontal"
ColumnHeaderHeight="10"
AlternatingRowBackground="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}"
CellStyle="{StaticResource CommonCell}"
AutoGeneratingColumn="DgDataTable_AutoGeneratingColumn">
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Background" Value="LightCyan"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.RowHeaderStyle>
</DataGrid>
change CellStyle for a generated column:
private void DgDataTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName == "ColorBackground")
{
e.Column.CellStyle = (sender as DataGrid).FindResource("ColorPickerCell") as Style;
}
}
Apply a Converter, this Converter is used for two diff. purpose hence returns two diff types. Beauty of this approach is : You can change the property in XAML itself. No change needed in code now, and hence it is MVVM friendly.
For example, in DataTrigger change Value=BkgProp to Value=Name and see.
Sample XAML :
<Window ...>
<Window.Resources>
<local:PropBasedStringToColorConverter x:Key="StringToColorCnvKey"/>
</Window.Resources>
<Grid>
<DataGrid x:Name="Dgrd">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding .Column, RelativeSource={RelativeSource Self}, Converter={StaticResource StringToColorCnvKey}}" Value="BkgProp">
<Setter Property="Background" Value="{Binding BkgProp, Converter={StaticResource StringToColorCnvKey}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
</Grid>
</Window>
Sample Data :
Dgrd.ItemsSource = new[] { new { BkgProp = "#abcdef", Name = "Anjum" }, new { BkgProp = "#edf2ed", Name = "Anjum" }, new { BkgProp = "#ff0000", Name = "Anjum" } }.ToList();
Converter Code :
public class PropBasedStringToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
object result = null;
if (value == null) return "N/A";
if (value.GetType() == typeof(DataGridTextColumn))
{
string path = ((Binding)((DataGridTextColumn)value).Binding).Path.Path;
return path;
}
else if (value.GetType() == typeof(string))
{
result = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value.ToString()));
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Align DataGrid Column Header to Center

I need to align WPF DataGrid Column Header text to Center. I created a style and attached that using the HeaderStyle property as below.
Style
<Window.Resources>
<Style x:Key="CenterGridHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</Window.Resources>
Column
<DataGridTextColumn
Binding="{Binding Path=Name}" Header="Name" IsReadOnly="True"
HeaderStyle="{DynamicResource CenterGridHeaderStyle}"/>
But this does not align Column Header text to the Center. How can I do this?
Check this
<DataGridTextColumn Header="Nombre"
Binding="{Binding Nombre}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Center" />
</Style>
</DataGridTextColumn.HeaderStyle>
It should be StaticResource instead of DynamicResource in the Column:
Style
<Window.Resources>
<Style x:Key="CenterGridHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</Window.Resources>
Column
<DataGridTextColumn
Binding="{Binding Path=Name}" Header="Name" IsReadOnly="True"
HeaderStyle="{StaticResource CenterGridHeaderStyle}"/>
There is a response for doing it programmatically at AutoGeneratingColumn:
private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column.HeaderStyle = new Style(typeof(DataGridColumnHeader));
e.Column.HeaderStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Center));
}
Tip, use attributes:
public class ColumnNameAttribute : Attribute
{
public HorizontalAlignment Alignment { get; set;}
public ColumnNameAttribute(HorizontalAlignment alignment){
Alignment = alignment;
}
public class Example(){
[ColumnName(HorizontalAlignment.Center)]
public string Column {get; set;}
}
private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var desc = e.PropertyDescriptor as PropertyDescriptor;
var att = desc.Attributes[typeof(ColumnNameAttribute)] as ColumnNameAttribute;
if(att != null){
e.Column.HeaderStyle = new Style(typeof(DataGridColumnHeader));
e.Column.HeaderStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, att.Alignment));
}
}
Try this
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.CellStyle>
I landed here while searching for the same problem for Row Headers alignment. In case anyone else was searching, the solution is as simple as:
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Style.Resources>
<Style TargetType="StackPanel">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
</DataGrid.RowHeaderStyle>
Here is what I am using to change the header text alignment.
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto" MinWidth="60" Header=" ID " IsReadOnly="True"> <DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="#c0c0c0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="12"/>
</Style> </DataGridTemplateColumn.HeaderStyle> <DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ID}" TextAlignment="Center" />
</DataTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Categories

Resources