Datagridview image column moves on update - vb.net

On my form i got datagridview which is populating by some data. There is also a combobx on this form and when selection change has happend then based on selected value - datagridview datasource is set to be nothing and then filled up again. Everything was working well until i decided to add additional datagridview image column which i placed on the end of grid and to show images based on text from some previous column text data. Unfortunetly i have problem with displaying images itself (red marks) and biggest problem is when i change combobox selection my additional datagrid image column is moving 1 position to left everytime combo is changed. I've spent whole day looking for issue but can't find any answer on that. I thought maybe that's because grid datasource is not being cleaned (nothing) but it is. Can you please help me out what could be a problem here? Below find my code and screenshoots of problem. Hope you help me to fix it as i am really stackoverflowed.
My Form Load event - that's where i load combobox:
Private Sub FrmTransportView_Load(sender As Object, e As EventArgs) Handles MyBase.Load
RemoveHandler CboProjects.SelectedIndexChanged, AddressOf CboProjects_SelectedIndexChanged
Try
mydb.OpenConn()
If mydb.conn.State = ConnectionState.Open Then
Form.InitCombo(CboProjects, "SELECT * from tbProjekt", mydb.conn, "Nazwa", "Id")
mydb.CloseConn()
'ChangeControlsLanguage()
Trans = New Transport
Trans.ProjectId = CboProjects.SelectedValue
RefreshGridAfterProjectIdChanged()
AddHandler CboProjects.SelectedIndexChanged, AddressOf CboProjects_SelectedIndexChanged
End Try
End Sub
PopulateGrid method:
Public Sub PopulateGrid()
Try
If IsNothing(Trans.ListByProjectId_checkifanyrows()) Then
Me.BeginInvoke(New MethodInvoker(AddressOf Me.Close))
Else
Else
dgvTransport.DataSource = Nothing 'Clean datagrid before new data
dgvTransport.Refresh()
dgvTransport.DataSource = Trans.ListByProjectId()
AlignGrid()
PlaceImages()
End If
End Try
End Sub
Align method - placed within PopulateGrid method as you see when dgvTransport as set to nohing and then its detasource set to new data: Trans.ListByProjectId() now i am aligning it - hiding some columns etc... As you can see also i am adding this new image column... :
Private Sub AlignGrid()
Try
dgvTransport.Columns(0).Visible = False 'Project id
dgvTransport.Columns(1).Visible = False 'Id
dgvTransport.Columns(2).Visible = True 'Lp
dgvTransport.Columns(3).Visible = True 'Status
dgvTransport.Columns(4).Visible = True 'Dataprzyjazdu
dgvTransport.Columns(5).Visible = True 'DataRozpoczeciaZaladunku
dgvTransport.Columns(6).Visible = True 'DataOdjazdu
dgvTransport.Columns(7).Visible = True 'TypTransportu dgvTransport.Columns(8).Visible = False 'TypKontenera (reprezentacja liczbowa z tabeli tbTransport)
dgvTransport.Columns(9).Visible = True 'NumerKontenera
dgvTransport.Columns(10).Visible = True 'NumerCiezarowki
dgvTransport.Columns(11).Visible = True 'Plomba
dgvTransport.Columns(12).Visible = False 'Kierowca
dgvTransport.Columns(13).Visible = False 'Opis
dgvTransport.Columns(14).Visible = False 'Nazwa (nazwa projektu)
dgvTransport.Columns(15).Visible = True 'TypKontenera (reprezentacja za pomoca nazwy ze zlaczenia INNER JOIN))
Dim img As DataGridViewImageColumn = New DataGridViewImageColumn()
img.HeaderText = "Status2"
img.Name = "Status2"
dgvTransport.Columns.Insert(16, img)
'potrzebny aby zadzialalo: DgvMach.ColumnHeadersDefaultCellStyle.BackColor = Color.Gold
dgvTransport.EnableHeadersVisualStyles = False
'headers look
With dgvTransport.ColumnHeadersDefaultCellStyle
'The way to do this is to set the EnableHeadersVisualStyles flag for the data grid view to False, and set the background colour via the ColumnHeadersDefaultCellStyle.BackColor property. For example, to set the background colour to blue, use the following (or set in the designer if you prefer):
'If you do not set the EnableHeadersVisualStyles flag to False, then the changes you make to the style of the header will not take effect, as the grid will use the style from the current users default theme. The MSDN documentation for this property is here.
.BackColor = Color.White
.ForeColor = Color.Black
.Font = New Font("Ariel", 10, FontStyle.Regular)
.Alignment = DataGridViewContentAlignment.MiddleCenter
End With
dgvTransport.AllowUserToAddRows = False
dgvTransport.[ReadOnly] = True
dgvTransport.MultiSelect = False
dgvTransport.SelectionMode = DataGridViewSelectionMode.FullRowSelect 'zaznacza caly wiersz po kliknieciu
dgvTransport.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.Fill 'WAZNE!!!: RESIZUJE CALY CONTENT GRIDA NIE ZOSSTAWIAJAC CIEMNEGO TLA !!!
dgvTransport.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
With dgvTransport.DefaultCellStyle
.BackColor = Color.White
.ForeColor = Color.Black
.Font = New Font("Ariel", 9, FontStyle.Regular)
.Alignment = DataGridViewContentAlignment.MiddleCenter
End With
'This will disable row autosizing and manual row resizing. To set the row height you can use the Height and MinimumHeight properties of the RowTemplate.
dgvTransport.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None
dgvTransport.AllowUserToResizeRows = False
End Sub
FrmTransportView_Shown event:
Private Sub FrmTransportView_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
AddHandler dgvTransport.SelectionChanged, AddressOf dgvTransport_SelectionChanged
End Sub
RefreshGridAfterProjectIdChanged
Public Sub RefreshGridAfterProjectIdChanged()
Trans.ProjectId = CboProjects.SelectedValue
PopulateGrid()
End Sub
CboProjects_SelectedIndexChanged
Private Sub CboProjects_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CboProjects.SelectedIndexChanged
RefreshGridAfterProjectIdChanged()
End Sub
PlaceImages
Private Sub PlaceImages()
For i As Integer = 0 To dgvTransport.Rows.Count - 1
Dim sHeader As String = dgvTransport.Columns(16).Name
If sHeader = "Status2" Then
Dim LINK = dgvTransport.Rows(i).Cells(8).Value
If LINK.ToString.Contains("1") Then
Dim Img As New DataGridViewImageCell
Img.Value = My.Resources._1
dgvTransport.Rows(i).Cells(16).Value = Img.Value
End If
If LINK.ToString.Contains("2") Then
Dim Img As New DataGridViewImageCell
Img.Value = My.Resources._2
dgvTransport.Rows(i).Cells(16).Value = Img.Value
End If
If LINK.ToString.Contains("3") Then
Dim Img As New DataGridViewImageCell
Img.Value = My.Resources._3
dgvTransport.Rows(i).Cells(16).Value = Img.Value
End If
End If
Next
End Sub
That's how it looks for first form load: (strange thing is column index of image column (Status2) is 0 - should be 16 as i placed index for that column to 16 in Align method.. As you see also not images are showing up...
Now when i am going to change selection in combobox:
of course as you can note from code this method handler is called: CboProjects_SelectedIndexChanged
so then again grid datasource will be set to Nothing, populate again, then align gird..
and that's what is shown after: (see indexes - also some image show up and column "Status2" was moved to left..)
3rd combobox change etc...
Hope to find someone here to help me out as i really have no idea how to fix that. Hope everything is clear.

Sorry this is coming a little late. Just a suggestion - I didn't experiment with it. Try to insert the DataGridImageColumn first before editing the visibility of the other columns.
Not too related, but in your AlignGrid sub, the static properties like ".BackColor" can be set on design just to reduce code.
Let us know your observations.
Thanks

Related

Missing members in custom progressbar

I am new in this field and I find myself in difficulty, I have already looked for two days on the internet and I have not found anything or at least that is understandable within my reach.
I downloaded a file for a new ProgressBar in 3d, but I no longer have the option of [Step] and [PerformStep], how can I add these two properties?
Please help me, I've been running after it for days....
I downloaded a file from this post https://social.msdn.microsoft.com/Forums/vstudio/en-US/5d3eee65-730b-488f-a858-a341b8d61714/progressbar-with-percentage-label?forum=vbgeneral at the bottom of the page the link for RmCustProgressBar but I have problems.
Here The file for download is file txt https://onedrive.live.com/?authkey=%21ADU6srhRub2eM6M&cid=00D11ED12923BE81&id=D11ED12923BE81%21114&parId=root&o=OneUp
Public Sub righeNere()
Dim row_count As Integer = DataGridView1.Rows.Count
RmCustProgressBar1.MaxValue = row_count
RmCustProgressBar1.Step = 1
Dim currencyManager1 As CurrencyManager = CType(DataGridView1.BindingContext(DataGridView1.DataSource), CurrencyManager)
For Each rw As DataGridViewRow In DataGridView1.Rows
If rw.Cells(2).Style.BackColor = Color.Gold Or rw.Cells(3).Style.BackColor = Color.Gold Or rw.Cells(4).Style.BackColor = Color.Gold Or rw.Cells(5).Style.BackColor = Color.Gold Or rw.Cells(6).Style.BackColor = Color.Gold Or rw.Cells(7).Style.BackColor = Color.Gold Then
rw.Visible = True
Continue For
ElseIf rw.Cells(2).Style.BackColor = Color.White Or rw.Cells(3).Style.BackColor = Color.White Or rw.Cells(4).Style.BackColor = Color.White Or rw.Cells(5).Style.BackColor = Color.White Or rw.Cells(6).Style.BackColor = Color.White Or rw.Cells(7).Style.BackColor = Color.White Then
currencyManager1.SuspendBinding()
rw.Visible = False
currencyManager1.ResumeBinding()
RmCustProgressBar1.PerformStep()
End If
Next
End Subd
I assume that Step is a step size and that PerformStep simply adds this step to the Value property. Then you can add this functionality like this in the progress bar class:
Public Property [Step] As Integer
Public Sub PerformStep()
Value = Math.Min(MaxValue, Value + [Step])
'To refresh the progress bar immediately (optional)
Refresh()
End Sub
Setting the Value property invalidates the control, i.e. the new progress bar position will be displayed automatically, but maybe with some delay. If you want to refresh it immediately, you can force a redraw by calling Refresh(). See: Control.Refresh Method
Note that Step is a reserved word in VB, therefore we must put it in angle brackets. Instead, we could also call it StepSize.

Dynamic entries from textfiles into FlowLayoutPanel

I'm currently working on a ToDo program, where you can simply add notes. (With the option to set priority and attachment) The Note will be saved as a textfile. Now I want to make an over view of the ToDo's which have to be done. In the end it's supposed to look like a list, one row for each Note, built like this:
TITLE.............................[Attachment Icon]..[Priority Icon]..[CheckBox]
The checkbox should always be on the very right side of the row.
My idea is to add a FlowLayoutPanel to a FlowLayoutPanel for every Note. In the child-FlowLayoutPanel I'll add the controls. My problem is that I have no Idea how to set the positions of the controls. I tried to add a label and use it as a space between the title and the other controls, but it doesn't really work.
Here's the code I currently have:
For Each File In Directory.GetFiles(myPath)
Dim tlp As New FlowLayoutPanel
tlp.BackColor = Color.Gray
tlp.Width = 260
tlp.FlowDirection = FlowDirection.TopDown
Dim lbl As New Label
lbl.AutoSize = True
lbl.Text = getInsert(File, 0)
lbl.Anchor = AnchorStyles.Right
lbl.ForeColor = Color.White
AddHandler lbl.Click, Sub() Me.getInsert(File, 0)
tlp.Height = 40
Dim cbx As New CheckBox
cbx.FlatStyle = FlatStyle.Flat
cbx.Text = ""
cbx.Width = 15
cbx.Height = 30
AddHandler cbx.CheckStateChanged, Sub() Me.deleteEntry(tlp)
Dim space As New Label
space.AutoSize = False
space.Text = ""
space.Height = 30
space.Anchor = AnchorStyles.Right
tlp.Controls.Add(lbl)
tlp.Controls.Add(Space)
tlp.Controls.Add(cbx)
Space.Width = tlp.Width - lbl.Width - cbx.Width - 15
mfp.Controls.Add(tlp)
Next
Here's an example:
todo_example
I hope anyone has a good idea how to solve this problem.
Thanks in advance :)

Visual Basic Datagrid View change row colour

Every other change to the datagrid view works fine but for some reason the row color just wont change.
Ive debugged and my application goes through the loop to change the row color.
Also I have a button that gives the datagrid view a new list and colors the rows accordingly, when I click the button the row colors changes do work!
Public Sub New(measuredValues As List(Of MeasuredValuesModel), valueType As ValueType)
IsFiltered = False
' This call is required by the designer.
InitializeComponent()
MeasuredValuesList = measuredValues
uxGrid.DataSource = MeasuredValuesList
uxGrid.Columns("StepID").Visible = False
uxGrid.Font = New Font("Arial", 10, FontStyle.Bold)
For Each c As DataGridViewColumn In uxGrid.Columns
Dim Column As DataGridViewColumn = c
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
Next
If valueType = StepItem.ValueType.CalculatedValues Then
uxButtonFilter.Visible = False
uxGrid.Columns("DISPOSITION").Visible = False
End If
For Each gridRow As DataGridViewRow In uxGrid.Rows
If gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "Y" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Red
ElseIf gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "N" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Orange
End If
Next
uxStepID.Text = MeasuredValuesList.FirstOrDefault.StepID
' Add any initialization after the InitializeComponent() call.
'TODO binding
End Sub
Here is the button that works for changing row color.
Maybe it works because it's pressed after the grid has been created? Im not too sure.
Private Sub uxButtonFilter_Click(sender As Object, e As EventArgs) Handles uxButtonFilter.Click
If IsFiltered = True Then
uxGrid.DataSource = MeasuredValuesList
For Each gridRow As DataGridViewRow In uxGrid.Rows
If gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "Y" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Red
ElseIf gridRow.Cells("PASSFAIL").Value.ToString() = "FAIL" And (gridRow.Cells("DISPOSITION").Value.ToString() = "N" Or gridRow.Cells("DISPOSITION").Value.ToString() = "N/A") Then
gridRow.DefaultCellStyle.BackColor = Color.Orange
End If
Next
Its the exact same loop but it seems to work fine when i use the button.
Is it possible that your datagridview isn't loaded fully when you try to recolor the rows?
Since you are setting the datasource, you should put your code that affects the grid after you can make sure that it is finished loading. The column widths change because it is not dependent on the data in the grid, but your colouring is.
Catch the uxGrid.databindingComplete event and try colouring the rows in there

Windows form controls become grey overlay

I have created a winform application in vb.net, it contains a parent container and other child forms. When one of the child form which contains a data gridview with some cell formatting, loading the other controls became gray colour overlayed.
Note: the gridview is created using the data from database and the color is applied according to the value in the cells. The color changing using the cellformating method. I have tried double buffering.. but it didn't help. In red color circle it is label and in green color, it is button.
Find the code below for cell formatting:
Private Sub dataGridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dataGridView1.CellFormatting
Try
Dim i As Integer
For i = 0 To dataGridView1.RowCount
If (i = (dataGridView1.RowCount)) Then
Exit For
Else
Dim dt As DateTime = DateTime.Parse(dataGridView1.Rows(i).Cells(6).Value.ToString())
dt = dt.AddHours(12)
Dim ts As TimeSpan = dt.Subtract(DateTime.Now)
Dim s As String = dataGridView1.Rows(i).Cells(7).Value.ToString()
If s = "Ready to Collect" Then
dataGridView1.Rows(i).Cells(7).Style.BackColor = Color.LimeGreen
dataGridView1.Rows(i).Cells(8).Value = "-----"
ElseIf s = "Completed" Then
dataGridView1.Rows(i).Cells(7).Style.BackColor = Color.GreenYellow
dataGridView1.Rows(i).Cells(8).Value = "-----"
ElseIf s = "Out of Stock" Then
dataGridView1.Rows(i).Cells(7).Style.BackColor = Color.Red
dataGridView1.Rows(i).Cells(8).Value = "-----"
ElseIf s = "Sent" Then
dataGridView1.Rows(i).Cells(7).Style.BackColor = Color.OrangeRed
If ts.CompareTo(TimeSpan.Zero) < 0 Then
dataGridView1.Rows(i).Cells(8).Value = "Process Immediately"
dataGridView1.Rows(i).Cells(8).Style.BackColor = Color.OrangeRed
Else
dataGridView1.Rows(i).Cells(8).Value = String.Format("{0:D2}:{1:D2}", ts.Hours, ts.Minutes)
End If
ElseIf s = "Cancelled" Then
dataGridView1.Rows(i).Cells(7).Style.BackColor = Color.White
dataGridView1.Rows(i).Cells(8).Value = "-----"
End If
End If
Next
Catch ex As Exception
System.Diagnostics.Trace.TraceError(ex.Message)
End Try
Check DoEvents. Maybe this helps you.

Width of drawn list box?

I've created a custom combobox that uses a custom instance of a listbox control as the dropdown menu.
In order to customize the selection highlight of the listbox, I had to change its 'DrawMode' property to 'OwnerDrawFixed' and added the following code:
Private Sub _listBox_DrawItem(sender As Object, e As DrawItemEventArgs)
If e.Index >= 0 Then
e.DrawBackground()
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
Using br = New LinearGradientBrush(e.Bounds, ColorSelectionListbox, ColorSelectionListbox, 0)
e.Graphics.FillRectangle(br, e.Bounds)
End Using
End If
Using b As New SolidBrush(ColorTextListbox)
e.Graphics.DrawString(_listBox.GetItemText(_listBox.Items(e.Index)), e.Font, b, e.Bounds)
End Using
e.DrawFocusRectangle()
RaiseEvent DrawItem(Me, e)
End If
End Sub
But with this, the width that I set for it is ignored and becomes a fixed width of 15 or so pixels.
How can I set the width of the owner-drawn control? Currently I have it as a property:
Public Property DropDownWidth() As Integer
Get
Return _dropDownWidth
End Get
Set(value As Integer)
_dropDownWidth = value
_listBox.Width = value
Invalidate(True)
End Set
End Property
Below is the rest of the code that is relevant, but nevermind.. I fixed the issue by setting the Autosize property of _controlHost to False. I had it set to True in order to display all items within the list (without having to define a dropdown maximum) but for some reason it behaves differently when the DrawMode is set to OwnerDraw.
_listBox = New ListBox()
_listBox.IntegralHeight = True
_listBox.BorderStyle = BorderStyle.FixedSingle
_listBox.SelectionMode = SelectionMode.One
_listBox.BindingContext = New BindingContext()
_dropDownWidth = Me.Width
_listBox.Width = _dropDownWidth
_controlHost = New ToolStripControlHost(_listBox)
_controlHost.Padding = New Padding(0)
_controlHost.Margin = New Padding(0)
_controlHost.AutoSize = False 'Used to be variable property _dropDownAutoSize
_popupControl = New ToolStripDropDown()
_popupControl.Padding = New Padding(0)
_popupControl.Margin = New Padding(0)
_popupControl.AutoSize = True '
_popupControl.DropShadowEnabled = False
_popupControl.Items.Add(_controlHost)