WPF : Custom DataGridRows with Custom style - wpf

i have a DataGrid, i want to add each row of this DataGrid, one by one, then check the information in that Row, if something in it (lets call it cancel) is true, that row is colored black, otherwise its colored white.
i'd also want to know how the contents in that row can be modified, like set text of each cell in it, and then add it to the DataGrid.

To fill and modify a DataGrid you bind an ObservableCollection to the DataGrid's ItemSource Property.
You can then modify the Collection as you like. For the layout you can use a Style.
<DataGrid ItemsSource="{Binding Collection}">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Cancel}" Value="false">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<!--
...
-->
</DataGrid>

Related

How do I set the style of a child based on AlternateIndex of parent?

I'm using a HeaderedItemsControl. Each item is a 3 column Grid with a Border and TextBlock in each column. I would like the background color of the Borders in each item to alternate. (Basic alternating row background effect.) I have attempted to create a style at the UserControl level for the Grid that applies a background color to all borders within it, based on the AlternationIndex of the containing control:
<Style TargetType="Grid" x:Key="myItemsGrid">
<Style.Resources>
<Style TargetType="Border">
<Setter Property="Background" Value="Azure" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AlternationIndex, RelativeSource={RelativeSource AncestorType=ItemsControl}}" Value="2">
<Setter Property="Background" Value="{StaticResource color_LogoLight}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
The Setter bit is working, as the borders are all "Azure". But how do I properly reference the AlternationIndex so that the border background color changes for every other row. I tried pointing the RelativeSource to HeaderedItemsControl and ItemsControl, but neither seems to be the proper target. I have browsed the live visual tree, but I can't find anything to reference, there.
Any help is appreciated.
You have to look for AlternationIndex on the Item of ItemsControl, not on ItemsControl itself! But which type you have to search in binding for? For example in ListBox it's a ListBoxItem and in ItemsControl it's a ContentPresenter.
Don't forget Path=(ItemsControl.AlternationIndex) and for your case (AlternationIndex==2) you have to set AlternationCount in ItemsControl at least to 3! So this code should work:
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType=ContentPresenter}}" Value="2">
<Setter Property="Background" Value="{StaticResource color_LogoLight}" />
</DataTrigger>

Changing DataGrid Row Styles while adding Items

I'm trying to change row style while adding items to DataGrid.
<DataGrid x:Name="datagrid1" HorizontalAlignment="Stretch" Height="auto" Margin="10,64,0,0"
VerticalAlignment="Stretch" Width="auto" AutoGenerateColumns="False" DataContext="{Binding}" ItemsSource="{Binding}">
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding UIvisibility}" Value="-2">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding UIvisibility}" Value="-1">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding UIvisibility}" Value="-0">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
</DataGrid>
kMS(i).line(7) has "-2","-1","-0" or "1" for each kMS(i) as String, And will be assigned to Item.Visibility
For Instance
kMS(1).line(7)="-1"
kMS(4).line(7)="-0"
kMS(369).line(7)="1"
kMS(897).line(7)="-2"
Codes are following
Dim c3 As DataGridTextColumn = New DataGridTextColumn
c3.Binding = New System.Windows.Data.Binding("UIvisibility")
c3.Visibility = 1
datagrid1.Columns.Add(c3)
Dim Additem(kMS.Length - 1) As Item
For i = 0 To kMS.Length - 1
Additem(i) = New Item
Additem(i).Callback = kMS(i).line(8)
Additem(i).Keyboard = "No Assign"
If kMS(i).line(3).Remove(0, 2) <> "FFFFFFFF" Then
Additem(i).Keyboard = kMS(i).line(3).Remove(0, 2)
End If
Additem(i).UIvisibility = kMS(i).line(7)
datagrid1.Items.Add(Additem(i))
Next
 
Public Class Item
Public Property Callback As String
Public Property Keyboard As String
Public Property UIvisibility As String
End Class
It's not working well and the result would be only rows with transparent background and black foreground.
Actutal image of the application
What am I missing?
It would help if you post a screenshot of your problem.
My guess is that you change the property of the wrong WPF control. For changing the background, DataGridRow is ok only for the part of the row which is not covered by any row. This can happen when the DataGrid is wider than all columns together.
For the columns, DataGridCell, i.e. TextBox gets painted over the DataGridRow. So if the DataGridRow is transparent, but the TextBox is white, you will see a white background.
This kind of problem WPF often avoids using graphical inheritance, meaning when a property is set in a container, all controls who don't write their own value for that property will inherit the value from the container.
Unfortunately, DataGrid behaves quite differently. Usually, your problems go away if you don't depend on graphical inheritance but style the correct control.
2 Recommendations
1) Don't use triggers to change the style. You can easily do it using bindings:
<datagrid.rowstyle>
<style targettype="DataGridRow">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self},
Path=Item.Quantity, Converter={StaticResource QuantityToBackgroundConverter}}"/>
</style>
</datagrid.rowstyle>
The Foreground could be done like this:
<Setter Property="Foreground"
Value="{Binding
RelativeSource={RelativeSource Self},
Path=Text,
Converter={StaticResource QuantityToForegroundConverter}}" />
2) Formatting the DataGrid is a major headache. I spent weeks trying to understand it. Read my article where I provide a lot of background information and many samples how important formattings can be done:
www.codeproject.com: Guide to WPF DataGrid formatting using bindings

style the new row on datagrid (CanUserAddRows)

How can I change the new row style (of CanUserAddRows) I want the user to notice to the new row.
thanks
I've not tested this, but I think it should work. You can try adding some Style for the DataGridRow. Add some Trigger listening to IsNewItem. Then you can change almost everything related to the matched DataGridRow via the Trigger Setter. The following code will try highlighting the new row by setting a red border around it:
<DataGrid ItemsSource="someSource">
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsNewItem" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<!-- remaining code ... -->
</DataGrid>

How to vertically center rows' contents in a WPF DataGrid?

I want to make the data record's VerticalAlignment=Center in DataGrid. By default,the data record's VerticalAlignment=Top, It looks uglily. Can you provide me this style?
I define my style in App.xaml file. The following is my current DataGrid style:
<Style x:Key="DataGridView" TargetType="DataGrid">
<Setter Property="AlternatingRowBackground" Value="AliceBlue"></Setter>
<Setter Property="AlternationCount" Value="1"></Setter>
<Setter Property="AutoGenerateColumns" Value="False"></Setter>
<Setter Property="GridLinesVisibility" Value="Horizontal"></Setter>
<Setter Property="VerticalGridLinesBrush" Value="DarkGray"></Setter>
<Setter Property="HorizontalGridLinesBrush" Value="DarkGray"></Setter>
<Setter Property="RowHeight" Value="32"></Setter>
</Style>
Try setting VerticalContentAlignment="Center" on the DataGrid:
<DataGrid VerticalContentAlignment="Center">
...
</DataGrid>
or you can add a setter to your style:
<Setter Property="VerticalContentAlignment" Value="Center"/>
When applied to ItemsControls, this property usually modifies alignment of each individual item container. In your case, this should make all rows align their contents to center.
UPDATE
Seems like the WPF built-in DataGrid doesn't follow the rule.
The solution depends on the type of the columns you use.
For DataGridTemplateColumn use a CellTemplate like this:
<DataTemplate>
<!--Substitute the TextBlock by the actual cell content, but don't drop VerticalAlignment-->
<TextBlock VerticalAlignment="Center" Text="{Binding Text}"/>
</DataTemplate>
For DataGridTextColumn, set ElementStyle:
<Style>
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center"/>
</Style>
I've tried this on DataGridTextColumn, but the property is from its parent DataGridBoundColumn, so should work for DataGridCheckBoxColumn and DataGridHyperlinkColumn also.
Update 2
BTW, there's another solution.

Set the Background of a DataGridRow based on the content of a cell

Is there a way, using XAML, to dynamically set the background of a row based on the content of one of it's cells?
Thanks,
Phil
You can define a style for a row and change the color using DataTrigger. Something like this:
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding BooleanPropertyOnObjectBoundToRow}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>
Here BooleanPropertyOnObjectBoundToRow is a boolean property on your data object one the cells is bound to.

Resources