Highlight Row TableLayoutPanel - c#

I'm trying to make a row of a TableLayoutPanel appear as highlighted when the user selects a cell. The row contains, for example, a Label in one column and a TextBox in the other. I've got this so far (when adding a Label):
Label label = new Label();
label.Text = text;
label.BackColor = Color.Blue;
label.Dock = DockStyle.Fill;
label.Margin = new Padding(0);
label.Anchor = AnchorStyles.Top | AnchorStyles.Left;
table.Controls.Add(label, col, row);
This works well, except there is a bit of whitespace above and to the left of the label. Any idea how to make it so that the entire cell is coloured?
I know about cell painting, but I prefer the above-mentioned approach.

Never mind, I realised that the TableLayoutPanel's border setting was "Inset", so it appeared as though there was whitespace. Changing it to "Single" fixed the issue.

Related

How do I make DataGridView header text align with cell text

The very standart WinForms DataGridView with some data (both columns are string) looks like this. Notice the header and data don't align, header has some empty space on the left (marked yellow on the first column).
How do I make it go away?
There are similar questions out there, but they are about header text being off-center, in this case it's left aligned.
What I tried:
grd.EnableHeadersVisualStyles = false;
column.HeaderCell.Style.Padding = new Padding(0, 0, 0, 0);
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
column.SortMode = DataGridViewColumnSortMode.NotSortable;
column.Resizable = DataGridViewTriState.False;
I know there is the CellPainting-Event I can probably use, but I'd really rather not.

C# WPF I have a dynamic grid of labels set up based off of a database. I need to set them up for drag and drop

I am fairly new to both C# and WPF, but the project I am working on seems to be a great fit for them. I have a dynamic grid of labels set up based off of a database. I need to set them up for drag and drop. I have some labels set up as header, and they are populated based off the next seven fridays. I made a function to pull the data from the database and compare each date to the content of the header label content. Then I make labels containing a job number and state for each of the dates that match with the header.
Kind of like this on load
content = Job# + " " + JobState
-Date+7n----Date+7n----Date+7n----Date+7n----Date+7n----Date+7n-----Date+7n
Content------Content-----Content-----Content-----Content-----Content------Content
Content------Content-----Content-----Content-----Content-----Content------Content
Content------Content-----Content--------------------Content-----Content------Content
Content---------------------Content--------------------Content-----Content------Content
Content---------------------Content--------------------Content---------------------Content
Pretty much when the date runs out of jobs it just doesn't make anymore labels for that column.
I tried to make it as dynamic and expandable as possible so I have a forward and backwards button that push all the dates up a week or back a week then repopulates the grid based off of the new date at the top.
private void AddLabel(ref int rowNum, string val, List<string>[] datGrid)
{
int rowLen;
int margin1;
int margin2;
var lb = new Label();
lb.HorizontalAlignment = HorizontalAlignment.Left;
lb.VerticalAlignment = VerticalAlignment.Top;
lb.Height = 32;
lb.Width = 155;
rowLen = datGrid[rowNum].Count;
lb.AllowDrop = true;
margin1 = 25 + (200 * (rowNum));
margin2 = 10 + (40 * (rowLen));
var gName = "grid" + (rowNum + 1) + (rowLen + 1);
lb.Margin = new Thickness(margin1, margin2, 0, 0);
lb.Content = val;
lb.Name = gName;
dyGrid.Children.Add(lb);
}
Where I put the row number that the label needs to be added to as rowNum, the actual content of the label as val and datGrid as the array of lists that holds the names for all the labels. I just can't figure out how to add a mouseDown or other drag and drop events to the labels as I make it.
The syntax you are looking for is
lb.MouseDown += new MouseButtonEventHandler(lb_MouseDown);
...
void lb_MouseDown(object sender, MouseButtonEventArgs e)
{
// Handle MouseDown event here.
Label lb = sender as Label;
}
But that said, I would recommend rethinking your design.
From what I can guess from your code, it sounds like you have a Grid (which allows it's children to overlap), and you are placing all the labels in the first cell of the Grid, and using the Margin property to position them. Its not a very efficient design, and will likely cause you problems in the future.
I would instead switch to using an ItemsControl bound to your collection of items, and drawing it's ItemsPanelTemplate as a Grid and your ItemTemplate as the Label. Then you can create data items so they represent the actual data item being represented by that item. Check out this similar answer if you want an example for what I am talking about.
Also if you do this, look up Bea Stollnitz's code for dragging/dropping databound items. Or some variation of it... I'm sure there's a copy of the code somewhere in my answer history too if you have questions.

Apply bold font to two consecutive rows in a datagridview

I have two consecutive rows in a datagridview, both of which need to be bold. I have changed the text colour for the lower row to red as follows. Although I can't seem to find a similar bold function.
cashBookRowsMarchTotals.Rows[1].DefaultCellStyle.ForeColor = Color.Red;
I made the two rows bold using the following code, but was wondering if it is possible to apply bold (or other styles) to multiple rows/columns at a time?
cashBookRowsMarchTotals.Rows[0].DefaultCellStyle.Font = new Font(cashBookRowsMarchTotals.Font, FontStyle.Bold);
cashBookRowsMarchTotals.Rows[1].DefaultCellStyle.Font = new Font(cashBookRowsMarchTotals.Font, FontStyle.Bold);
I saw your answer and I feel like let you know about the CellFormatting Event of the dataGridView. It is actually built to format the dataGridView based from the row index or column values.
This code example changes the font based on the value of a column but you can easily change it to filter by the row index instead of the column value.
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// Change the color of the row if the value on column1 is > 0
if (e.ColumnIndex == 1 && Convert.ToDecimal(e.Value) > 0) // Column1
{
this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Red; // Set font color red
this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.Font = new System.Drawing.Font(this.Font, FontStyle.Bold); // Set Bold
}
if (e.ColumnIndex == (int)transactionsDGV.AmountDue && Convert.ToDecimal(e.Value) <= 0) // Column Amount Due
{
this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.ForeColor = Color.Black; // Set font color black
}
}
Use Poperty of DataGridView
RowsDefaultCellStyle Click on Ellipse [...] and Set the Font Properties

TableLayoutPanel Winforms not showing all information

I have a really strange set of circumstances that I just can't seem to get to work. I will let you know what I have and see If you can put me right. (The below represents the closest I have been able to get to what I want).
The idea is that when a day is selected I show a usercontrol that has a lorry's deliveries for that day.
The thing is that the date may be a range. Therefore I have the following setup thus far:
I have a
TableLayoutPanel (Dock = Fill; 1 column (100percent); 1 Row (Autosize).
Then each selected has a user control (ucSchedulerDay) this is added as a row to the TableLayoutPanel. So take a single day for example, you would have this:
TableLayoutPanel (Dock = Fill; 1 Column (100%); 1 Row (Autosize).
- (Row1 Column1) ucSchedulerDay
So the ucSchedulerDay is just a user control that houses a GroupBox (Dock=Fill) and a FlowLayoutPanel (also dock=fill inside the groupbox)
For each lorry I have another usercontrol added to the FlowLayoutPanel (these have a fixed width) so essentially what I have is the following for one single day
TableLayoutPanel (as above (also forgot to mention that AutoScrollBars=True)
- (Row 1 Column 1) ucSchedulerDay (Dock=Fill(done in code when added))
- GroupBox (Dock=Fill)
- FlowLayoutPanel (Dock=Fill)
- ucLorryDay1
- ucLorryDay2
This works fine as long as all the lorries fit on the screen (see above), so for one day with 2 lorries(or even up to 5 on my monitor) then it's ok. However, if I select two days or make the screen smaller, instead of showing the scroll bars but generally having the same layout, it cuts some of the ucLorryDays up and just doesn't display others.
Note on the above pic how the grey lorry is cut off, even the scroll bar doesn't extend that far.
I don't understand why this isn't working. I would really appreciate any help on this, please let me know if you need more information.
Ok, So I think that the nested GroupBox/UserControl-GroupBox idea was where it all went wrong. I have fixed this by updating the original form to do the following:
pnlLorries.Controls.Clear();
DateTime dt_start = monthView1.SelectionStart;
DateTime dt_end = monthView1.SelectionEnd;
int rowCounter = 0;
for (DateTime dt = dt_start; dt.Date <= dt_end; dt = dt.AddDays(1))
{
Label lbl = new Label();
Font ft = new System.Drawing.Font("Calibri", 12);
lbl.Text = dt.ToShortDateString();
lbl.Font = ft;
pnlLorries.Controls.Add(lbl, 0, rowCounter);
rowCounter++;
FlowLayoutPanel pnl = new FlowLayoutPanel();
pnl.Dock = DockStyle.Fill;
pnl.AutoSize = true;
DataTable tbl = cDALSettings.DB.GetCannedTable("select * from lorry");
// Now we simply add these controls to the panel...
foreach (DataRow row in tbl.Rows)
{
ucLorryDay ld = new ucLorryDay(dt, cTypes.ToInt(row["id"]), this);
pnl.Controls.Add(ld);
}
pnlLorries.Controls.Add(pnl, 0, rowCounter);
rowCounter++;
}
So I create it all and add in the label. The downside is of course that it is not in a neat little box but even when I did it this way with a groupbox it came back with the same results I was experiencing before. I suppose the problem was the panel inside a panel (inception style).

How to get the ScrollViewer to scroll after statically set index containing List inside?

I am using Silverlight 5 and C# to create a scroll bar.
I am have ListBox and I create a scrollbar and inside that scrollbar I display a List of items like this: (My code shows all the 7 items but I just want to display 3 items without scrolling rest 4 by scrolling)
TextBlock txtblkShowStatus = null;
ListBox lines = new ListBox();
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
lines.ItemsSource = param.Component.Attributes.Items;
scrollViewer.Content = lines;
scrollViewer.HorizontalAlignment = HorizontalAlignment.Center;
scrollViewer.VerticalAlignment = VerticalAlignment.Center;
scrollViewer.ScrollToVerticalOffset(3); //By this line i want to display the only 3 items (out of7).
//I mean the other 4 items must be visible on scrolling.
Grid.SetColumn(scrollViewer, 1);
childGrid.Children.Add(scrollViewer);
txtblkShowStatus = generateTextBlock();
lines.SelectionChanged += (o, e) =>
{
txtblkShowStatus.Text = lines.SelectedItem.ToString();
};
lines.SelectedIndex = 2; //It will display énd item in txtblkShowStatus when no clikc happens at starting.
Grid.SetColumn(txtblkShowStatus, 2);
childGrid.Children.Add(txtblkShowStatus); //This childGrid contain a row with 3 columns.
By this line scrollViewer.ScrollToVerticalOffset(3); i want to display only 3 items out of 7 .I mean the other 4 items must be visible on scrolling the scrollbar.
NOTE: Please note that i don't have to use height , i need to deal with index because i will set the index statically and it must show just the values until that index and rest value will be displayed on scrolling. (if you have anyother idea to achieve it please explain it).
How to do the achieve this?
This is similar to rae1's suggestion,
int index = 5; //say you want to display upto 5th element
ListBox lines = new ListBox();
lines.Width = 100;
ScrollViewer scrollViewer = new ScrollViewer();
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
for (int i = 0; i < 5; i++)
{
lines.Items.Add(new ListBoxItem
{
Content = i.ToString()
});
}
foreach (ListBoxItem lv in lines.Items)
{
lv.Height = 10;
}
scrollViewer.Height = index * 10;
scrollViewer.Content = lines;
Grid.SetColumn(scrollViewer, 1);
childGrid.Children.Add(scrollViewer);
The ScrollToVerticalOffset method does not do what you are trying to use it for. It will scroll only when there is a need to. In your case you are seeing all 7 elements because the space allows you to see them.
If you want to only show the first three items you need to modify the Height property for the ScrollViewer and set it to a proper value.
If you have 7 items, and each items is 10px in height, and the height of the ScrollViewer is 100px there is not need to scroll because all items can be fitted in the space given. However, if you change the height to 30px, then the ScrollViewer only has 30px to display a 70px content size, and thus you need to scroll to see the rest of the items, achieving the effect you are after.

Categories