I have a program consist of combo box:
Have the designer like:
this.month_list.AllowDrop = true;
this.month_list.FormattingEnabled = true;
this.month_list.Items.AddRange(new object[] {
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"});
this.month_list.Location = new System.Drawing.Point(35, 13);
this.month_list.Name = "month_list";
this.month_list.Size = new System.Drawing.Size(75, 24);
this.month_list.TabIndex = 13;
Now my question is it possible to disable the month selection visibility if month option is future or next to current month? Or in other words say now is march,so the user will not able to click APR,MAY and so-on. Any idea please advise.
Add a handler on the year ComboBox.SelectedIndexChanged, and in it repopulate the month list based on the current date and year selected.
If year is 2014, then don't add the month greater than the current one to your month list.
EDIT:
private void yearCombo_SelectedIndexChanged(object sender, EventArgs e)
{
if(int.Parse(yearCombo.Text) > DateTime.Now.Year)
{
//remove all entries from ComboBox
}
else if (int.Parse(yearCombo.Text) == DateTime.Now.Year)
{
//Just add the months up to current month
}
else
{
//Add all months
}
}
Sadly to tell that disable item in combobox only supported in VS2003-2005.
You may only remove them via the below code (If you wish to remove the item from the existing combobox):
// To remove item with index 0:
this.month_list.Items.RemoveAt(0);
// To remove currently selected item:
this.month_list.Items.Remove(this.month_list.SelectedItem);
// To remove "JAN" item:
this.month_list.Items.Remove("JAN");
The below code is combining the idea of Luc Morin's answer jonathanh8686's answer which you may find it helpful:
First you make a dictionary as what jonathanh8686's answer stated:
Dictionary<int,string> months = new Dictionary<int,string>();
months.add(1, "Jan");
months.add(2, "Feb");
Then everytime when the user change the year Combobox, you reset the month combobox as below:
private void yearCombo_SelectedIndexChanged(object sender, EventArgs e)
{
if(int.Parse(yearCombo.Text) > DateTime.Now.Year)
{
//remove all entries from ComboBox
this.month_list.Items.Clear();
}
else if (int.Parse(yearCombo.Text) == DateTime.Now.Year)
{
//Just add the months up to current month
this.month_list.Items.Clear();
int monthnumber = 1;
while(monthnumber <= DateTime.Now.Month)
{
this.month_list.Items.Add(months[monthnumber]);
monthnumber++;
}
}
else
{
//Add all months
this.month_list.Items.Clear();
int monthnumber = 1;
while(monthnumber <= 12)
{
this.month_list.Items.Add(months[monthnumber]);
monthnumber++;
}
}
}
I'm a newbie at C# so im not the best person to answer this but I have a idea about how to do this
I'm not sure about the exact code for this but heres a idea that could be used:
Make a datetime that contains the month
int month = 1;
int monthnumber = 1;
Datetime dt = new DateTime();
Then you could make a dictionary that has a key of the number month and key of the number of month so like:
Dictionary<int,string> months = new Dictionary<int,string>();
months.add(1, "Jan");
months.add(2, "Feb");
and so on...
after that do check for the month and look at the current month so if its March
if(dt.Month = March)
{
month = 3;
}
so then after that
add all the months that are less than 3 like this:
while(monthnumber < months)
{
this.month_list.Items.Add(dates.Value);
monthnumber++;
}
You would have to write custom code to draw the items of the combo box yourself.
Add these event handlers to the month list as well:
this.month_list.DrawMode = DrawMode.OwnerDrawFixed;
this.month_list.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.comboBox1_DrawItem);
this.month_list.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
Font font = new Font("Aerial", 10, FontStyle.Regular);
bool DisableIndex(int index)
{
return index > DateTime.Now.Month - 1;
}
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
Brush brushToDrawWith = DisableIndex(e.Index) ? Brushes.LightSlateGray : Brushes.Black;
e.Graphics.DrawString(this.month_list.Items[e.Index].ToString(), font, brushToDrawWith, e.Bounds);
}
void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DisableIndex(month_list.SelectedIndex))
{
month_list.SelectedIndex = -1;
}
}
Related
I place a dropdownlist into my web page, then add following code to bind items to dropdown list within the page load event.
In this case is a dropdownlist with month names.
On this dropdownlist when the month changes, the previous months are no longer displayed and the previous month is no longer shown after the day 20th of the following month.
How can I also exclude from the list the months following the one on the list?
E.G.
At this time in the dropdownlist month list I have the months included from February to December
After the twentieth day of month February I will have in dropdownlist the months included from March to December
The question is to see only March in dropdownlist month and not see following months (from April to December...)
public partial class DD_Monthbind : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Monthbind();
}
}
private void Monthbind()
{
DateTimeFormatInfo info = DateTimeFormatInfo.GetInstance(null);
int currentMonth = DateTime.Now.Month;
for (int i = 1; i < 13; i++)
{
bool isMonthInPast = ((i + 1) < currentMonth) || (i + 1 == currentMonth && DateTime.Now.Day > 20);
if (!isMonthInPast)
DropDownList1.Items.Add(new ListItem(info.GetMonthName(i), i.ToString()));
}
}
}
update
private void Monthbind()
{
DateTimeFormatInfo info = DateTimeFormatInfo.GetInstance(null);
int currentMonth = DateTime.Now.Month;
for (int i = 1; i < 13; i++)
{
bool isMonthInPast = (i < currentMonth) || (i == currentMonth && DateTime.Now.Day > 20);
if (!isMonthInPast)
{
DropDownList1.Items.Add(new ListItem(info.GetMonthName(i), i.ToString()));
}
}
foreach (ListItem item in DropDownList1.Items)
{
if (DropDownList1.Items.IndexOf(item) != 0)
{
item.Enabled = false;
}
}
}
I am working on access based WinForm application. I have colored cell(DateColumn) in my DataGridView. I am trying to count colored cells as shown in pic and want to reflect total No. of colored cell on a label's text. I tried below codes which are not counting my DataGridView's total No. of colored cells although counting total rows. Exact problem can be understand with the help of this image
My Codes are as follows:
private void metroGrid1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.metroGrid1.Columns[e.ColumnIndex].DataPropertyName == "Date 1")
try
{
var EMIDate1 = Convert.ToDateTime(metroGrid1.Rows[e.RowIndex].Cells["date1DataGridViewTextBoxColumn"].Value);
for (int i = 0; i < metroGrid1.RowCount; i++)
{
if (EMIDate1 <= DateTime.Today)
{
int countDarkRed = 0;
e.CellStyle.BackColor = Color.DarkRed;
e.CellStyle.ForeColor = Color.White;
foreach (DataGridViewRow row in this.metroGrid1.Rows)
{
if (row.Cells["date1DataGridViewTextBoxColumn"].Style.BackColor == Color.DarkRed)
{
countDarkRed++;
}
}
labelEMI.Text = "Total EMI due as on today:" + countDarkRed;
}
}
}
catch
{
}
}
Short answer
You want to set the styles in the grid's cell, not only in the current formatting session of the cell. You are colouring the wrong CellStyle. Directly access the grid cell style instead of using the event cell and your code will do what you want (tested on my machine):
if (EMIDate1 <= DateTime.Today)
{
this.metroGrid1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.DarkRed;
this.metroGrid1[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.White;
}
Long Answer
DONT DO THIS
The formatting event will be applied only on VISIBLE cells
rows or columns hidden because the control/windows is too small will not trigger this code
You are mixing formatting logic (colours) with business logic (expired dates)
try to do this check before even binding the grid, or make another call to the database
The documentation explicitly discurage to do too much process inside the cell formatting event
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.cellformatting?view=netframework-4.7.2#remarks
This code will be executed every time there is a windows redraw, mouse over, etc, making your label one of the most expensive labels in your program
you should make that counting just once
Complete working example
Create a window form application with just one datagridview and a label
public Form1()
{
InitializeComponent();
dataGridView1.DataSource = new[] {
new {Title = "bella", Date1 = DateTime.Now.AddDays(1)},
new {Title = "ciao", Date1 = DateTime.Now.AddDays(12)},
new {Title = "bella", Date1 = DateTime.Now.AddDays(-1)},
new {Title = "ciao", Date1 = DateTime.Now.AddDays(-31)},
new {Title = "bella", Date1 = DateTime.Now.AddDays(11)},
new { Title= "ciao", Date1 = DateTime.Today} ,
new { Title= "ciao", Date1 = DateTime.Today} ,
new { Title= "ciao", Date1 = DateTime.Today.AddDays(-7)} };
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName == "Date1")
{
var date = dataGridView1.Rows[e.RowIndex].Cells["Date1"].Value as DateTime?;
if (date.HasValue && date.Value <= DateTime.Today)
{
dataGridView1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.DarkRed;
dataGridView1[e.ColumnIndex, e.RowIndex].Style.ForeColor = Color.White;
}
int countDarkRed = 0;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells["Date1"].Style.BackColor == Color.DarkRed)
countDarkRed++;
}
label1.Text = $"dark = {countDarkRed}";
}
}
Where you went wrong in the previous case was, you were checking only the first cell and kept incrementing the count, now you've confused my comments on your previous question. Here's the outline:
There is one if loop to check the date and change color, and one for loop to count the number of cells that have changed color
private void metroGrid1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.metroGrid1.Columns[e.ColumnIndex].DataPropertyName == "Date 1")
{
try
{
int countDarkRed = 0;
var EMIDate1 = Convert.ToDateTime(metroGrid1.Rows[e.RowIndex].Cells["date1DataGridViewTextBoxColumn"].Value);
//Checking whether we have to turn it red or not
if (EMIDate1 <= DateTime.Today)
{
e.CellStyle.BackColor = Color.DarkRed;
e.CellStyle.ForeColor = Color.White;
}
//Checking how many cells have turned red
foreach(DataGridViewRow row in this.metroGrid1.Rows)
{
if (row.Cells["date1DataGridViewTextBoxColumn"].Style.BackColor == Color.DarkRed)
{
countDarkRed++;
}
}
labelEMI.Text = "Total EMI due as on today:" + countDarkRed;
}
catch
{
}
}
}
I have a combo box that I'm using to select a month out of a year. The months are provided through a List<> that I've set as the data source.
I believe I'm going about this the wrong way.
Code So Far:
private void btnExport_Click(object sender, EventArgs e)
{
int month = 0; //just a default value
if (cbMonth.SelectedText == "January")
month = 1;
else if (cbMonth.SelectedText == "Febuary")
month = 2;
else if (cbMonth.SelectedText == "March")
month = 3;
else if (cbMonth.SelectedText == "April")
month = 4;
else if (cbMonth.SelectedText == "May")
month = 5;
else if (cbMonth.SelectedText == "June")
month = 6;
else if (cbMonth.SelectedText == "July")
month = 7;
else if (cbMonth.SelectedText == "August")
month = 8;
else if (cbMonth.SelectedText == "September")
month = 9;
else if (cbMonth.SelectedText == "October")
month = 10;
else if (cbMonth.SelectedText == "November")
month = 11;
else if (cbMonth.SelectedText == "December")
month = 12;
int year = Int32.Parse(mtbYear.Text);
MessageBox.Show(month.ToString() + " " + year.ToString()); // to check values
}
My month never changes value and displays as 0. Which, I understand because I had given it the initial value of 0 in order to pass it to another method.
Question: How can I get the numeric value for the months when the user selects them from my combo box?
Show months in ComboBox:
comboBox1.DataSource = System.Globalization.CultureInfo.InvariantCulture
.DateTimeFormat.MonthNames.Take(12).ToList();
Select current month:
comboBox1.SelectedIndex = DateTime.Now.Month - 1;
Get selected month:
MessageBox.Show($"Month: {comboBox1.SelectedIndex + 1} - {comboBox1.SelectedItem}");
Have you tried the SelectedValue of the Combobox?
private void btnExport_Click(object sender, EventArgs e)
{
int month = 0; //just a default value
var monthNumber = DateTime.ParseExact((string)cbMonth.SelectedValue, "MMMM", CultureInfo.InvariantCulture).Month;
int year = Int32.Parse(mtbYear.Text);
MessageBox.Show(monthNumber.ToString() + " " + year.ToString()); // to check values
}
Don't forget to add try-catch for ParseExact
Hey whenever you see yourself using this many if elses, try to simplify the logic.
IDictionary<string, int> monthsDictionary = new Dictionary<string, int>()
{
{January,"1"},
{February, "2"},
{March,"3"}
/* And so on */
};
Declare this dictionary with the months you are using. Then you can just look at what the selected value of the cbo box is and use that as the key. Just make sure that the values in the cbo box match the keys in the dictionary. Like so.
private void btnExport_Click(object sender, EventArgs e)
{
month = monthsDictionary[cbMonth.SelectedText];
//This will give you the value of the key.
//Ex. If march is chosen then 3 is what is given back as an int.
int year = Int32.Parse(mtbYear.Text);
MessageBox.Show(month.ToString() + " " + year.ToString()); // to check values
}
I hope this helps!
You may use ParseExact method of DateTime. Ex -
var monthNumber = DateTime.ParseExact(cbMonth.SelectedText, "MMMM", CultureInfo.InvariantCulture).Month;
To get the numeric value from a list, i.e.
<asp:DropDownList ID="cbMonth" runat="server">
<asp:ListItem Selected="True" Value="1" Text="January"></asp:ListItem>
<asp:ListItem Value="2" Text="February"></asp:ListItem>
</asp:DropDownList>
The Selected value of this will give you the numeric value:
private void btnExport_Click(object sender, EventArgs e)
{
int month = cbMonth.SelectedValue;
}
Display the Month name at the font end but in value attribute store the month in number and when you select the month from combo box at that time in background you will get the month in digit
I'm new into programing and still learning. Currently I'm coding simple form for my schedule program (c#) in MS Visual Studio 2017. I already program day in month grid ( when you change date program generate gridview for it) but I have two important problem:
I would like to get day number in each cell, I tried use loop while and foreach but it doesn't work....
Second thing is that I would like to save my appointment in cell.
If its possible I would rather not use database, and I really don't want to use solutions that I would have to pay.
Here's my code:
namespace WindowsFormsApp1
{
public partial class Kalendarz : Form
{
public Kalendarz()
{
InitializeComponent();
}
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
DateTime date_start = this.dateTimePicker1.Value;
this.textBox2.Text = date_start.ToString("hh-mm-dd-MM-yyyy"); // czas startu
this.textBox1.Text = date_start.ToString("MMMM");
int Month = date_start.Month;
int Year = date_start.Year;
int NoD = DateTime.DaysInMonth(Year, Month);
Decimal NoWD = Decimal.Divide(NoD, 7.0m);
if (NoWD > 4.1m)
{
int WN = 5;
dataGridView1.RowCount = WN;
int n0 = 1;
foreach(DataGridCell cell in dataGridView1)
{
while (n0 = NoD; n0++)
}
}
else
{
int WN = 4;
dataGridView1.RowCount = WN;
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
dataGridView1.Columns["s"].Visible = true;
dataGridView1.Columns["st"].Visible = true;
}
else if (!checkBox1.Checked)
{
dataGridView1.Columns["s"].Visible = false;
dataGridView1.Columns["st"].Visible = false;
}
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
}
Do you have any suggestions what can I do ?
I found something like that but I don't have any idea how to loop it
dataGridView.CurrentCell.Value = newValue.ToString ();
Be careful, what you whish for...
Regarding 1st request: This code will fill a DataGridView with day numbers, starting on the set day in week and not exceeding number of days in month, provided you have enough rows an columns, filling it from left to right (as opposed to i.e. top-down). I'd advice 7 columns, unless you want to have a lot of fun with calendar.
Guessing from your name, you're Polish and as far as I know week starts with Monday in Poland. You'd need a modification to the code for week starting with Sunday.
VB.NET:
Dim DayCounter As Int16 = 1
Dim DayInWeekStart As Int16 = 2 ' 1 = MON, 2 = TUE, 3 = WED, ...
Dim DayInMonthTotal As Int16 = 31
For ir = 0 To Me.dgv.rows.count - 1
For ic = 0 To Me.dgv.columns.count - 1 ' you should have 7 columns for MON-SUN in your DataGridView
If ir = 0 And (ic + 1) < DayInWeekStart And DayCounter < DayInMonthTotal Then
' skip / do nothing
Else
Me.dgv.rows(ir).cells(ic).value = DayCounter ' set DGV cell value to the date
DayCounter += 1 ' iterate day in month number
End If
Next
Next
C# (converted):
Int16 DayCounter = 1;
Int16 DayInWeekStart = 2;
// 1 = MON, 2 = TUE, 3 = WED, ...
Int16 DayInMonthTotal = 31;
For (ir = 0; ir <= this.dgv.rows.count - 1; ir++) {
// you should have 7 columns for MON-SUN in your DataGridView
For (ic = 0; ic <= this.dgv.columns.count - 1; ic++) {
If (ir == 0 & (ic + 1) < DayInWeekStart & DayCounter < DayInMonthTotal) Then {
// skip / do nothing
} else {
this.dgv.rows(ir).cells(ic).value = DayCounter;
// set DGV cell value to the date
DayCounter += 1;
// iterate day in month number
}
}
}
As for saving, the best option would be definitely a database, even though a structured text file is doable. If you have a lot of time...
For database, I'd use MERGE statement to UPDATE, DELETE or INSERT appointments.
I have a ListView on another form that I populate with this code
if (choice <= 1)
{
ListViewItem items = new ListViewItem(new[]
{
activity, statusType, blueprintName, runs, installerName, actTime, endDate, location
});
lstvw.Items.Add(items);
}
I change the data on the ListView with several different outputs using this code or similar for the other outputs.
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
listView1.Visible = false;
listView1.Items.Clear();
rbInt = 1;
choice = rbInt + cbInt;
listviewcolumnbuilder();
worker.IndustryReturns(choice, listView1);
this.Text = "Industry Jobs - All Jobs";
listView1.Visible = true;
}
I want to update a specific cell, in this case actTime, that is a DateTime that I convert to a string. That value specifically counts down to 0 on certain date.
What would be a good way to update just that specific cell automatically?