Color autogeneratedcolumn cells using IValueConverter WPF - wpf

I would like to ask you if it's possible to change autogeneradetcolumn cells color using Converter?
My Datagrid in xaml:
<DataGrid ItemsSource="{Binding FillDG}" x:Name="ListHoliday"
HorizontalAlignment="Left" Height="186" VerticalAlignment="Top"
Width="880" Grid.Column="1" Margin="10.4,103,0,0" Grid.Row="1"/>
codebehind:
Dim sql As String
Dim startDate As Date = dtStartV.SelectedDate
Dim endDate As DateTime = dtEndV.SelectedDate
Dim numberOfDays As Integer = ((endDate.Date) - (startDate.Date)).Days + 1
sql = "SELECT Enumber, HType, HStartDate, HEndDate from tbl_HolidayLog"
Dim da As New SqlDataAdapter(sql, cnn)
Dim dt As New DataSet
da.Fill(dt, "Holiday")
With Me.ListHoliday
.ItemsSource = dt.Tables("Holiday").DefaultView
End With
For dayCount As Integer = -1 To (numberOfDays - 0)
Dim currentDate As Date = Convert.ToDateTime(startDate.AddDays(dayCount))
Dim formatedD As String = currentDate.ToString("dd/MM")
If currentDate.DayOfWeek <> DayOfWeek.Saturday AndAlso currentDate.DayOfWeek <> DayOfWeek.Sunday Then
Dim c1 As New DataGridTextColumn
c1.Header = Format(currentDate, "MMMM") & vbCrLf & formatedD
ListHoliday.Columns.Add(c1)
For Each item As DataRowView In ListHoliday.ItemsSource
Dim saDate As DateTime = item.Item("HStartDate")
Dim enDate As DateTime = item.Item("HEndDate")
Dim numberOfHeader As Integer = ((enDate.Date) - (saDate.Date)).Days - 0
For dayCountHeader As Integer = 0 To (numberOfHeader - 0)
count(dayCountHeader) = 0
Next dayCountHeader
Next
End If
Next dayCount
I don't have any name for columns because 4 of theme are from table and the rest (dates) are created programmatically. And I would like to color cells in those programmatically created columns. Converter could be like:
Dim V As SolidColorBrush = Brushes.White
Dim holi As New HolidayLog
For Each hitem As DataRowView In holi.dgMyTeamView.ItemsSource
Dim hType As String = hitem.Item("HType")
If hType.Trim() = "Vacation" Then
V = Brushes.Blue
End If
Next
Return V
But I don't know how can I bind this to each autogenerated date cell/column.
Thank you very much for any advice!

You can set CellStyle of DataGrid which will be picked up by autogenerated columns cell.
<DataGrid>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background"
Value="{Binding Converter={StaticResource ColorConverter}}"/>
</Style>
</DataGrid.CellStyle>
</DataGrid>
UPDATE:
You can pass the Column to converter and color only in case Column is the one you want to color.
<DataGrid>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background"
Value="{Binding Column,
RelativeSource={RelativeSource Self},
Converter={StaticResource ColorConverter}}"/>
</Style>
</DataGrid.CellStyle>
</DataGrid>
Converter:
DataGridColumn column = value as DataGridColumn;
// Check for property name here.
if (column != null && column.Header.ToString() == "Name")
{
return Brushes.Blue;
}
return Brushes.White;

Related

Datagrid focus to selected row

I have a simple datagrid with some itemssource. I select a row and go to other control. Every time i focus the grid again using tab, it selects the first row and cell. (It show a black border box on first cell)
I have set the IsSynchronizedWithCurrentItem="True" but not working
I want the previous selected row to get focus.
"it selects the first row and cell" no in fact the selection remains as it was but yes when the focus returns to datagrid the focused cell will change to the first cell.
Check if this approach suits you, it's the simplest I came with so far!:
First, add event handler to cell GotFocus and LostFocus as follows:
<DataGrid x:Name="list_1">
<DataGrid.Columns >
<DataGridTextColumn Header="ID" Width="30" Binding="{Binding id}"/>
<DataGridTextColumn Header="Name" Width="50" Binding="{Binding name}"/>
<DataGridTextColumn Header="UserID" Width="50" Binding="{Binding user_id}"/>
</DataGrid.Columns>
<DataGrid.CellStyle >
<Style TargetType="DataGridCell" >
<EventSetter Event="GotFocus" Handler="cgf"/>
<EventSetter Event="LostFocus" Handler="clf"/>
</Style>
</DataGrid.CellStyle>
</DataGrid>
In your code behind, add the following code:
Private WithEvents timer1 As New Threading.DispatcherTimer With {.Interval = New TimeSpan(0, 0, 0, 0, 50)}
Private WithEvents timer2 As New Threading.DispatcherTimer With {.Interval = New TimeSpan(0, 0, 0, 0, 50)}
Dim LastFocusedCell As DataGridCell
Dim focus_lost As Boolean
Sub cgf(sender As object, e As RoutedEventArgs)
timer1.Stop()
If focus_lost Then
focus_lost = False
If LastFocusedCell IsNot Nothing Then
list_1.IsReadOnly = True
LastFocusedCell.Focus()
timer2.Start()
Else
LastFocusedCell = sender
End If
Else
LastFocusedCell = sender
End If
End Sub
Sub clf(sender As Object, e As RoutedEventArgs)
timer1.Start()
End Sub
Private Sub tmr_Tick(sender As Object, e As EventArgs) Handles timer1.Tick
timer1.Stop()
focus_lost = True
End Sub
Private Sub tmr2_Tick(sender As Object, e As EventArgs) Handles timer2.Tick
timer2.stop()
list_1.IsReadOnly = False
End Sub
I don't think it's the best approach but it worked fine for me.

WPF VB.Net Datagrid Value from a specific Cell in FullRow Selection Mode?

How can I get a Value from a specific Cell in a Datagrid with the Selection Mode FullRow ?
At the moment I use this command, but it only display's the Value if I manually select the cell:
Public Sub MenuItem_Click(sender As Object, e As RoutedEventArgs)
Dim selectedData As String = ""
Dim wert As String = ""
For Each dataGridCellInfo In myGridView.SelectedCells()
Dim pi As Reflection.PropertyInfo = dataGridCellInfo.Item.[GetType]().GetProperty(dataGridCellInfo.Column.Header.ToString())
Dim value = pi.GetValue(dataGridCellInfo.Item, Nothing)
selectedData += dataGridCellInfo.Column.Header + ": " + value.ToString() + vbLf
wert = value.ToString
Next
MessageBox.Show(selectedData)
End Sub
But I don't want to manually select the cell all time.
I just want to click on any cell in that Row and get always the value from the cell "Pfad" and put it in a String.
XAML DataGrid Code:
<DataGrid Name="myGridView" SelectionUnit="Cell" IsReadOnly="True" ItemsSource="{Binding}" Grid.ColumnSpan="3" Background="#FFA4A4A4" BorderThickness="2" BorderBrush="#FF6A6F77" AutoGenerateColumns="False" Margin="10,31,10,149.714" GridLinesVisibility="None">
<DataGrid.Columns>
<DataGridTextColumn Header="Track" Binding="{Binding Path=Track}" Width="100"/>
<DataGridTemplateColumn Header="">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Width="50" Height="50" VerticalAlignment="Center" HorizontalAlignment="Center" Source="{Binding Path=Image}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Path=Endung}" Width="100" Header=" Container"/>
<DataGridTextColumn Binding="{Binding Path=Album}" Width="100" Header="Album"/>
<DataGridTextColumn Binding="{Binding Path=Bitrate}" Width="100" Header="Bitrate"/>
<DataGridTextColumn Binding="{Binding Path=Pfad}" Width="100" Header="Pfad"/>
</DataGrid.Columns>
</DataGrid>
Code-Behind:
Public Structure Austauscher
Dim files As New ObservableCollection(Of Austauscher)
Private _track As String
Private _image As BitmapImage
Private _album As String
Private _pfad As String
Private _bitrate As String
Private _endung As String
Property Track() As String
Get
Return _track
End Get
Set(ByVal Value As String)
_track = Value
End Set
End Property
Property Image As BitmapImage
Get
Return _image
End Get
Set(ByVal Value As BitmapImage)
_image = Value
End Set
End Property
Property Album() As String
Get
Return _album
End Get
Set(ByVal Value As String)
_album = Value
End Set
End Property
Public Property Pfad As String
Get
Return _pfad
End Get
Set(ByVal Value As String)
_pfad = Value
End Set
End Property
Property Bitrate As String
Get
Return _bitrate
End Get
Set(ByVal Value As String)
_bitrate = Value
End Set
End Property
Property Endung As String
Get
Return _endung
End Get
Set(ByVal Value As String)
_endung = Value
End Set
End Property
End Structure
At first you need tu open de event "CellClick" on your datagridview and put de following code:
If (e.ColumnIndex <> -1) And (e.RowIndex <> -1) Then
Dim selectedCell as string = ""
selectedCell = myGridView.rows(e.rowIndex).cells("numberOfCell").valeu
End If
If this Answer has help you. Pleas mark this at the correct Answer.

I am having trouble binding DataGridComboBoxColumn to a datatable

I am new to WPF and I am having trouble with something that should seem like a simple job . I have a data table that I am trying to bind to a DataGridComboBoxColumn. This is my code = please advise. No combobox is showing on loading.
<CollectionViewSource x:Key="ColorListData"/>
<DataGridComboBoxColumn Header="Color" ItemsSource="{Binding Source= {StaticResource ColorListData}}" x:Name="myColorComboBox" DisplayMemberPath="ColorName" SelectedValuePath="DataID" />
code behind:
Dim ColorListData As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("ColorListData"), System.Windows.Data.CollectionViewSource)
Dim Sql As String = "Select DataID, ColorName from Colors where StyleID = #StyleID"
ReDim SqlP(0)
SqlP(0) = MyData.CreateParameter("StyleID", SqlDbType.Int, 4, StyleID)
Dim MyColorTable As DataTable = MyData.GetDataTable(Sql, "text", SqlP)
ColorListData.Source = MyColorTable.DefaultView

DAL Generator: How to get Grid Checkbox?

I am building a WPF D.A.L. generator.
In my main page, I have a DataGrid populated with a list of the tables in my database.
I also have an extra checkbox column called ShouldInclude? I intend to use this to determine whether or not the table should be included in the generation... yes if checked, no if un-checked.
Because I am populating the DataGrid's ItemSource with a strongly typed list of some basic info TableName, Schema, Columns, I am now finding myself at a loss as to how I can get the checked value of the checkbox so I can make that determination on whether to include it or not.
Here are my functions that build out my table typing class code files:
Private Sub GenerateTyping(ByVal _DG As DataGrid)
For Each i As TableTyping In _DG.Items
'check if should be generated
Dim _TString As String = String.Empty
Using _sr As New StreamReader(Common.GetPath() & "Class Templates\CSharp\Typing\XXX_Typing.txt")
_TString = _sr.ReadToEnd()
_sr.Close()
End Using
Dim _FN As String = i.Name & "_Typing.cs"
Dim _Props As New StringBuilder()
Dim _CL As List(Of ColumnTyping) = i.Columns
For Each col In _CL
With _Props
Dim _PropStr As String = "public " & Common.GetClrType(col.Type) & " " & col.Name & " { get; set; }"
.AppendLine(" " & _PropStr)
End With
Next
'Write the new class files
_TString = _TString.Replace("##TABLENAME##", If(i.Schema.Length > 0, i.Schema & "_", "") & i.Name).Replace("##THE_PROPERTIES##", _Props.ToString())
If Not Directory.Exists(FilePath & "\Typing\") Then
Directory.CreateDirectory(FilePath & "\Typing\")
End If
Using _sw As New StreamWriter(FilePath & "\Typing\" & If(i.Schema.Length > 0, i.Schema & "_", "") & i.Name & "_Typing.cs", False)
_sw.Write(_TString)
_sw.Close()
End Using
_TString = String.Empty
_Props.Clear()
Next
End Sub
Partial Public Class TableTyping
Public Property ID As Integer
Public Property Name As String
Public Property Schema As String
Public Property Columns As List(Of ColumnTyping)
End Class
Partial Public Class ColumnTyping
Public Property ID As Integer
Public Property Name As String
Public Property Type As SqlDataType
Public Property Length As Integer
Public Property DefaultValue As String
Public Property Precision As Integer
Public Property Scale As Integer
End Class
My datagrid simply consists of 3 columns. Include?, Table Schema, Table Name, which is populated via:
<DataGrid EnableRowVirtualization="True" Name="dgTables" IsReadOnly="True" AutoGenerateColumns="False" FontFamily="Calibri" FontSize="14" IsEnabled="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Include?">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding ID}" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="True" Name="ckTblInclude" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Schema}" Header="Schema"/>
<DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
</DataGrid.Columns>
</DataGrid>
AND:
_tg.ItemsSource = _Table
Private Sub GrabTables()
Dim _Db As Database = Srv.Databases(DBName)
Dim _Tbls As TableCollection = _Db.Tables
Dim _tct As Integer = _Tbls.Count
Dim _i As Integer = 0
For i = 0 To _tct - 1
If Not _Tbls(i).IsSystemObject Then
_i += 1
_Tables.Add(New TableTyping() With {
.ID = _i,
.Name = _Tbls(i).Name,
.Schema = _Tbls(i).Schema,
.Columns = ProcessColumns(_Tbls(i).Columns)})
End If
Next
_TCount = _Tables.Count
End Sub
_Tables is a List(of TableTyping)
How can I do the Include? check inside the GenerateTyping procedure?
I had to change my checkbox template to the following:
<CheckBox Tag="{Binding ID}" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Include, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Name="ckTblInclude" />
And change the _Tables list to populate via:
Private Sub GrabTables()
Dim _Db As Database = Srv.Databases(DBName)
Dim _Tbls As TableCollection = _Db.Tables
Dim _tct As Integer = _Tbls.Count
Dim _i As Integer = 0
For i = 0 To _tct - 1
If Not _Tbls(i).IsSystemObject Then
_i += 1
_Tables.Add(New TableTyping() With {
.ID = _i,
.Name = _Tbls(i).Name,
.Schema = _Tbls(i).Schema,
.Columns = ProcessColumns(_Tbls(i).Columns),
.Include = True})
End If
Next
_TCount = _Tables.Count
End Sub

Alignment on dynamically created items

Hi,
Based on the image above, I would like to align the words "Action", "Adventure", "Arcade" to left most and align it to appear same height as the blue right arrow
my code for this is created dynamically:
Dim intRow As Integer
Dim intColumn As Integer
intRow = 0
intColumn = 0
Dim rd As RowDefinition
For Each abc In ArrayOfItems
Dim newButton As New Button
newButton.MaxHeight = 35
newButton.MaxWidth = 300
newButton.Background = Brushes.Transparent
newButton.BorderBrush = Brushes.Transparent
newButton.Tag = abc.application_category_id
Dim sp As New StackPanel
sp.Orientation = Orientation.Horizontal
sp.HorizontalAlignment = Windows.HorizontalAlignment.Left
sp.VerticalAlignment = Windows.VerticalAlignment.Center
Dim Image2 As New Image
Dim src As New Uri("/Images/chevron_blue.png", UriKind.Relative)
Dim img As New BitmapImage(src)
Image2.Width = 10
Image2.Height = 10
Image2.HorizontalAlignment = Windows.HorizontalAlignment.Left
Image2.VerticalAlignment = Windows.HorizontalAlignment.Left
Image2.Source = img
Dim LabelApp As New Label
LabelApp.Content = abc.category_name
LabelApp.FontWeight = FontWeights.Bold
LabelApp.FontSize = 9
LabelApp.MaxWidth = 270
LabelApp.Foreground = Brushes.Black
LabelApp.HorizontalContentAlignment = Windows.HorizontalAlignment.Left
LabelApp.VerticalAlignment = Windows.HorizontalAlignment.Left
sp.Children.Add(LabelApp)
sp.Children.Add(Image2)
newButton.Content = sp
Grid.SetColumn(newButton, intColumn)
Grid.SetRow(newButton, intRow)
gridCategoryGames.Children.Add(newButton)
intRow = intRow + 1
rd = New RowDefinition With {.Height = GridLength.Auto}
gridCategoryGames.RowDefinitions.Add(rd)
gridCategoryGames.UpdateLayout()
Next abc
End If
Ouch, that is an ugly way to do it :)
Fortunately WPF has something that will cut your code down substantially, the ItemsControl. As you already have ArrayOfItems which is obviously IEnumerable, you can craft you XAML like this:
<ItemsControl ItemsSource="{Binding ArrayOfItems}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Vertical" HorizontalAlignment="Right" >
<TextBlock Text="myText"/>
<Image Source="path to my image" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can then get rid of all that code that is manually creating items. The controls specified in ItemsControl.ItemTemplate will be repeated for every item in your list. The sky is the limit with this approach (there are literally thousands of examples of how to use this control).

Resources