Why can't I create an array of an object I created? - c#

The objective is to create a spreadsheet kind of program such as Microsoft Excel. I have created a cell class which I want to create multiple instances of. Is the syntax incorrect or am I missing something logically?
What I did so far:
- Create a cell class.
- Initialized array, only to get an error.
public partial class form_welcomeScreen : Form
{
Label[] cellLetters = new Label[26];
Label[] cellNumbers = new Label[26];
Cell cell[] = new Cell[26];
char cellLetter = 'A';
int cellNumber = 1;
public form_welcomeScreen()
{
InitializeComponent();
}
private void Btn_newSheet_Click(object sender, EventArgs e)
{
for (int i = 0; i < 26; i++)
{
Cell cell = new Cell();
pnl_main.Controls.Add(cell.createCell());
cell.CellLetter = cellLetter;
cell.CellNumber = cellNumber;
cellLetter++;
cellNumber++;
}
}
}
class Cell : System.Windows.Forms.TextBox
{
private char cellLetter;
private int cellNumber;
private string cellID;
public char CellLetter
{
get { return cellLetter; }
set { cellLetter = value; }
}
public int CellNumber
{
get { return cellNumber; }
set { cellNumber = value; }
}
public string CellID
{
get { return cellID; }
set { cellID = CellLetter + Convert.ToString(CellNumber); }
}
public TextBox createCell()
{
TextBox cell = new TextBox();
cell.AcceptsReturn = true;
cell.Name = cellID;
cell.Size = new System.Drawing.Size(50, 25);
return cell;
}
I expect an array to be created so I can be able to create a whole spreadsheet of cells rather than just the one.

The line:
Cell cell[] = new Cell[26];
gives you mismatched types (cell vs cell[]). It should be:
Cell[] cell = new Cell[26];

Related

How to display details from an object to a TextBox

I am making a program which will test if an airplane is allowed to fly or not. It's my very first personal project using Windows Form and C#. I made a lot of progress, however, I am having a huge problem with a feature I want to have. I have two forms called Main & FlightSetup and the second form uses a class called AircraftClass which contains constructors, behaviours, and properties.
PROBLEM
I will try to make it simple and understandable. I am calling class AircraftClass inside public void addaircraftButton_Click to make an object and store all necessary details like aircraftModel,airlineName, etc. However, I have a ListBox called aircraftList which shows only the aircraft name. The idea is to display all that data/details depending on what the user selects from the aircraftList inside a TextBox called detailsList (yes, I called it like that, but it's a textbox). This is when the issue happens, it is not displaying the correct information, and it's showing the properties value for AircraftClass
NOTES
aircraftList & detailsList are inside Main Form - I do know that there are some obvious mistakes here, but I am still learning, please go easy on me :(
Variables Inside Main Form
int planeCount = 0; int tailNumber = 0; int planeIndex;
string planeModel = "NONE"; string airline = "NONE";
double distanceM = 0.0; double fuelG = 0.0; double maxKG = 0.0; double totalKG = 0.0;
int passengers= 0; int bag1=0; int bag2 = 0;
Main Code (Only addbuttom method)
public void addaircraftButton_Click(object sender, EventArgs e)
{
FlightSetup addAircraft = new FlightSetup(); //CREATES INFO INSIDE DETAILS
string nl = "\r\n";
using (addAircraft)
{
DialogResult result = addAircraft.ShowDialog();
planeModel = addAircraft.planeModel_textbox.Text;
airline = addAircraft.airline_textbox.Text;
tailNumber = int.Parse(addAircraft.tailno_textbox.Text);
passengers= int.Parse(addAircraft.passengerTextBox.Text);
bag1 = int.Parse(addAircraft.carryonTextBox.Text);
bag2= int.Parse(addAircraft.checkedBagsTextBox.Text);
distanceM = double.Parse(addAircraft.distance_textbox.Text);
fuelG = double.Parse(addAircraft.fuel_textbox.Text);
maxKG = double.Parse(addAircraft.maxweight_textbox.Text);
AircraftDetails test = new AircraftDetails(planeModel,airline,tailNumber,passengers,bag1,bag2,distanceM,fuelG,maxKG,totalKG);
test.AircraftModel = addAircraft.planeModel_textbox.Text;
MessageBox.Show("Flight Setup is COMPLETED! \n\nPerfom Unit Testing For Take-Off Permission", "FLIGHT SAVED!");
planeCount++;
noaircraft_label.Text = planeCount.ToString();
aircraftList.Items.Add(planeModel + " - REGULAR ROLE");
}
}
Main Code (Only aircraftList method)
public void aircraftList_SelectedIndexChanged(object sender, EventArgs e) //PENDING SOLUTION
{
AircraftDetails getData = new AircraftDetails();
StringBuilder insertData = new StringBuilder(String.Empty);
string nl = "\r\n";
planeIndex = aircraftList.SelectedIndex;
if (planeIndex > -1)
{
insertData.Append(getData.AircraftModel.ToString());
insertData.Append(nl);
detailsList.Text = insertData.ToString();
}
}
AircraftClass Code
{
public class AircraftDetails
{
string aircraftModel = "UNKNOWN";
string airlineName = "UNKNOWN";
int id = 0; //not in use
int tailNumber = 0;
int passengerNo = 0;
int carrybag = 0;
int checkbag = 0;
double distance = 0.0;
double fuel = 0.0;
double mWeight = 0.0;
double totalWeight = 0.0;
int errorCount = 0;
//Constructors
public AircraftDetails()
{
aircraftModel = "UNKNOWN";
airlineName = "UNKNOWN";
id = 0;
tailNumber = 0;
passengerNo = 0;
carrybag = 0;
checkbag = 0;
distance = 0.0;
fuel = 0.0;
mWeight = 0.0;
totalWeight = 0.0;
}
public AircraftDetails(string aircraftModel, string airlineName, int tailNumber, int passengerNo, int carrybag, int checkbag, double distance, double fuel, double mWeight, double totalWeight)
{
this.aircraftModel = aircraftModel;
this.airlineName = airlineName;
this.tailNumber = tailNumber;
this.passengerNo = passengerNo;
this.carrybag = carrybag;
this.checkbag = checkbag;
this.distance = distance;
this.fuel = fuel;
this.mWeight = mWeight;
this.totalWeight = totalWeight;
}
//BEHAVIOUR
public override string ToString()
{
if (this.passengerNo >= 1)
return "Aircraft: " + aircraftModel + "\r\n Tail Number:" + tailNumber + "\r\nOperator: " + airlineName + "\r\nAircraft: " + "\r\nFlight Distance: " + distance + "\r\nFuel: " + fuel +
"\r\nMax Weight Allowed: " + mWeight + "\r\nTotal Weight: " + totalWeight + "\r\nPassengers: "+passengerNo+ "\r\nCarry-On Bags: "+carrybag+ "\r\nChecked Bags: "+checkbag;
else
{
errorCount++;
return "Passengers were less than 0\r\nIt means error was recorded\r\nError Count: "+errorCount;
}
}
//Properties
public string AircraftModel
{
get { return aircraftModel; }
set { aircraftModel = value; }
}
public string Airline
{
get { return airlineName; }
set { airlineName = value; }
}
public int TailNumber
{
get { return tailNumber; }
set { tailNumber = value; }
}
public int PassengerNo
{
get { return passengerNo; }
set { passengerNo = value; }
}
public int OnBoardBags
{
get { return carrybag; }
set { carrybag = value; }
}
public int CheckedBags
{
get { return checkbag; }
set { checkbag = value; }
}
public double FlightDistance
{
get { return distance; }
set { distance = value; }
}
public double Fuel
{
get { return fuel; }
set { fuel = value; }
}
public double MaxWeight
{
get { return mWeight; }
set { mWeight = value; }
}
}
}
Your question is how to display details from an object to a TextBox.
I see in your code that you've done a good job of overriding the ToString method. In a sense, you answered your own question because that's what it takes!
But let's try and boil all that code into a minimal reproducible example that will include data binding as Jimi so rightly recommended. The bare bones of our bindable class has this override:
// Minimal example of a class
class AircraftDetails : INotifyPropertyChanged
{
public override string ToString()
{
List<string> builder = new List<string>();
builder.Add($"{Airline} {Flight}");
builder.Add($"FlightStatus: {FlightStatus}");
builder.Add($"{OnboardBags} bags onboard");
builder.Add($"{CheckedBags} bags checked");
builder.Add($"Total bags: {TotalBags}");
builder.Add($"Fuel onboard: {Fuel.ToString("F2")}");
return string.Join(Environment.NewLine, builder);
}
.
.
.
public event PropertyChangedEventHandler? PropertyChanged;
}
Next, write the main form code to display details from an object to a TextBox.
One salient point is that ToString() can just be called on object because it's virtual.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
buttonShowObjectInTextbox.Click += onButtonShowObjectInTextbox;
}
private void onButtonShowObjectInTextbox(object? sender, EventArgs e)
{
// For demonstration purposes, make an object.
// (Make sure parameterless constructor `AircraftDetails(){ }` is present)
object o = new AircraftDetails
{
Flight = "UA2907",
Airline = Airline.United,
Fuel = 50000,
OnboardBags = 237,
CheckedBags = 500,
};
textBoxMultiline.Text = o.ToString();
}
}
Your question also states I have a ListBox called aircraftList....
When a listbox is bound to BindingList<AircraftDetails> you can choose a property of your AircraftDetails class to show as the DisplayMember property.
Add code to the main form's Load event to set up the data source and the ListBox:
public partial class MainForm : Form
{
.
.
.
BindingList<AircraftDetails> Details = new BindingList<AircraftDetails>();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
aircraftDetails.DataSource = Details;
aircraftDetails.DisplayMember = nameof(AircraftDetails.Flight);
aircraftDetails.SelectedIndexChanged += onAircraftDetailsSelection;
// Add a few flights
Details.Add(new AircraftDetails
{
Flight = "UA6026",
Airline = Airline.United,
Fuel = 45250,
OnboardBags = 155,
CheckedBags = 97,
});
Details.Add(new AircraftDetails
{
Flight = "UA8888",
Airline = Airline.United,
Fuel = 27620,
OnboardBags = 301,
CheckedBags = 134,
});
Details.Add(new AircraftDetails
{
Flight = "WN8610",
Airline = Airline.Southwest,
Fuel = 200,
OnboardBags = 5,
CheckedBags = 614,
});
aircraftDetails.SelectedIndex = -1;
}
In response to selection changes, call this method to show object in textbox:
private void onAircraftDetailsSelection(object? sender, EventArgs e)
{
if(aircraftDetails.SelectedItem != null)
{
textBoxMultiline.Text = aircraftDetails.SelectedItem.ToString();
}
}
}

How to show the attributes of an object when clicking a button in Windows forms?

I want to show the attributes of an object when I click on a button in Windows Forms using c# and I don't know how to do it. Part of my code looks like this until now. I'm a beginner in c#.
class Pizza: ICloneable
{
private string nume;
private int nrIngrediente;
private string[] ingrediente;
public Pizza()
{
nume = "Margherita";
nrIngrediente = 2;
ingrediente = new string[nrIngrediente];
for (int i = 0; i < nrIngrediente; i++)
{
ingrediente[0] = "Sos rosii";
ingrediente[1] = "Mozzarella";
}
}
public Pizza(string den, int nri, string[] ing)
{
nume = den;
nrIngrediente = nri;
ingrediente = new string[nrIngrediente];
for (int i = 0; i < nrIngrediente; i++)
ingrediente[i] = ing[i];
}
public Pizza(Pizza p)
{
nume = p.nume;
nrIngrediente = p.nrIngrediente;
ingrediente = new string[nrIngrediente];
for (int i = 0; i < nrIngrediente; i++)
ingrediente[i] = p.ingrediente[i];
}
public string PizzaName
{
get { return nume; }
set { nume = value; }
}
public int PizzaNrIng
{
get { return nrIngrediente; }
set { nrIngrediente = value; }
//also, i don't know how to write the getter and setter for this one
public string PizzaIngredients
//{
// get
// {
// for(int i=0;i<nrIngrediente;i++)
// return ingrediente[i];
// }
// set { ingrediente = value; }
//}
And now, the form code is the following(note that i designed it already):
public partial class ListaPizza : Form
{
public ListaPizza()
{
InitializeComponent();
}
private void Margherita_Click(object sender, EventArgs e)
{
string[] ingrMargh = new string[2] { "Sos rosii", "Mozzarella" };
Pizza Margherita = new Pizza("Margherita", 2, ingrMargh);
//Show(Margherita);
//here i want the object created above to be shown in a messagebox when i click the button in the form but i don't know how
}
}
Thank you!
MessageBox.Show();
has to be a string value so any parts of your object that is not a string will need the .ToString() method
Or if you want to customize the view you could pass the object to a new form and create a whole nice layout for it with the designer.
You can set the getter and setter in below way.
public string PizzaIngredients
{
get
{
return String.Join(",",nringrediente);
}
set
{
nringrediente = value.Split(',');
}
}
And Show(Margherita); can be implemented like in Pizza Class :
public string GetDisplayMessageForPizza()
{
return "My Pizza is " + nume + ". It contains " + nringrediente + " ingredients : " + PizzaIngredients;
}
And in form ListaPizza :
private void Margherita_Click(object sender, EventArgs e)
{
string[] ingrMargh = new string[2] { "Sos rosii", "Mozzarella" };
Pizza Margherita = new Pizza("Margherita", 2, ingrMargh);
MessageBox.Show(Margherita.GetDisplayMessageForPizza());
}
As for the getter - you should return an array of strings, not just a string:
public string[] PizzaIngredients
{
get
{
ingrediente;
}
set
{
ingrediente = value;
}
}
As for the showing - just use MessageBox.Show():
MessageBox.Show(string.Format("{0} {1}", Margherita.Name, Margherita.nrIngrediente));

Access list in class from another class

I know this is asked before, but I can't seem to figure it out.
I have a class which makes a list from a datagridview. I want to do stuff with this list in another class but I cant't access it. I can access it from Form1.cs like the code underneath. How do I access the list from a random class like I can in Form1.cs?
//Opens the file dialog and assigns file path to Textbox
OpenFileDialog browseButton = new OpenFileDialog();
private void browse_Click(object sender, EventArgs e)
{
browseButton.Filter = "Excel Files |*.xlsx;*.xls;*.xlsm;*.csv";
if (browseButton.ShowDialog() == DialogResult.OK)
{
ExcelPath.Text = browseButton.FileName;
fileExcel = ExcelPath.Text;
//SetAttributeValue(ExcelPath, fileExcel);
//nylp();
/*
////IMPORTERER 10TAB-DATA FRA EXCEL TIL DATAGRIDVIEW////
tenTabLine.fileExcel = fileExcel;
tenTabLine.tenTab(tenTabDgv);
*/
////IMPORTERER NYLPDATA TIL DATAGRIDVIEW////
nylpLine.fileExcel = fileExcel;
nylpLine.nylpData(nylpDgv);
////TAR DATA I NYLPDGV DATAGRIDVIEW OG BEREGNER VERTIKALE ELEMENTER////
vertElementer.vertBueDGV(nylpDgv, vertElementerDgv);
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(vertElementerDgv);
MessageBox.Show(TEST[5].p2.ToString());
}
else return;
}
When I try to do something like this I get lot of errors in Error List:
class GetKoord
{
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(vertElementerDgv);
MessageBox.Show(TEST[5].p2.ToString());
}
This is my list class
class GetVertElementasList
{
private List<vertEl> vertElementList = new List<vertEl>();
public List<vertEl> vertList(DataGridView VertElementer)
{
for (int i = 0; i<VertElementer.Rows.Count - 1; i++)
{
vertElementList.Add(new vertEl
{
elNr = (int)VertElementer.Rows[i].Cells[0].Value,
p1 = (double)VertElementer.Rows[i].Cells[1].Value,
p2 = (double)VertElementer.Rows[i].Cells[2].Value,
z1 = (double)VertElementer.Rows[i].Cells[3].Value,
z2 = (double)VertElementer.Rows[i].Cells[4].Value,
heln1 = Convert.ToDouble(VertElementer.Rows[i].Cells[5].Value),
heln2 = (double)VertElementer.Rows[i].Cells[6].Value
});
}
return vertElementList;
}
}
public class vertEl
{
private int _elNr;
private double _p1;
private double _p2;
private double _z1;
private double _z2;
private double _nylpRad;
private double _heln1;
private double _heln2;
public int elNr
{
get { return _elNr; }
set { _elNr = value; }
}
public double p1
{
get { return _p1; }
set { _p1 = value; }
}
public double p2
{
get { return _p2; }
set { _p2 = value; }
}
public double z1
{
get { return _z1; }
set { _z1 = value; }
}
public double z2
{
get { return _z2; }
set { _z2 = value; }
}
public double nylpRad
{
get { return _nylpRad; }
set { _nylpRad = value; }
}
public double heln1
{
get { return _heln1; }
set { _heln1 = value; }
}
public double heln2
{
get { return _heln2; }
set { _heln2 = value; }
}
}
EDIT:
I've made it work now except that I get a out of range exception.
class code is:
class GetKoord
{
public GetVertElementasList getList = new GetVertElementasList();
BridgGeometry obj = new BridgGeometry();
public void foo()
{
var TEST = getList.vertList(obj.vertElementerDgv);
MessageBox.Show(TEST[2].elNr.ToString());
}
}
In form1 or BridgGeometry as it is called in my project I have which is giving me out of range exception.
GetKoord getZ = new GetKoord();
getZ.foo();
EDIT2:
The code underneath works and gives a message box with some value in list. But the method foo() in class above gives a out of range error.
private void browse_Click(object sender, EventArgs e)
{
browseButton.Filter = "Excel Files |*.xlsx;*.xls;*.xlsm;*.csv";
if (browseButton.ShowDialog() == DialogResult.OK)
{
////TESTING////WORKING CODE AND GIVES A MESSAGEBOX WITH VALUE
GetVertElementasList getVertList = new GetVertElementasList();
var TEST = getVertList.vertList(vertElementerDgv);
MessageBox.Show(TEST[2].elNr.ToString());
}
else return;
}
I think you are trying to access the variable directly in the class; which will not work. Try following
class GetKoord
{
GetVertElementasList getList = new GetVertElementasList();
public void foo()
{
var TEST = getList.vertList(vertElementerDgv);
MessageBox.Show(TEST[5].p2.ToString());
}
}
I tested your code and it seemed to worked. My code for you and #Anand
No Errors, except for empty Lists. But thats because I didn't fed it any information. So, there shouldn't be a problem.
#Grohl maybe try my code and comment where the error is displayed. This should be the most easy way to find the problem.
TestClass which represents class GetKoord
namespace TestForm
{
class TestClass
{
public TestClass()
{
DataGridView tmp = new DataGridView();
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(tmp);
MessageBox.Show(TEST[5].p2.ToString());
}
}
}
The GetVertElementasList
namespace TestForm
{
class GetVertElementasList
{
private List<vertEl> vertElementList = new List<vertEl>();
public List<vertEl> vertList(DataGridView VertElementer)
{
for (int i = 0; i < VertElementer.Rows.Count - 1; i++)
{
vertElementList.Add(new vertEl
{
elNr = (int)VertElementer.Rows[i].Cells[0].Value,
p1 = (double)VertElementer.Rows[i].Cells[1].Value,
p2 = (double)VertElementer.Rows[i].Cells[2].Value,
z1 = (double)VertElementer.Rows[i].Cells[3].Value,
z2 = (double)VertElementer.Rows[i].Cells[4].Value,
heln1 = Convert.ToDouble(VertElementer.Rows[i].Cells[5].Value),
heln2 = (double)VertElementer.Rows[i].Cells[6].Value
});
}
return vertElementList;
}
}
//Some other stuff
}
Last but not least. the code from the button click event:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
DataGridView tmp = new DataGridView();
GetVertElementasList getList = new GetVertElementasList();
var TEST = getList.vertList(tmp);
MessageBox.Show(TEST[5].p2.ToString());
TestClass tmpClass = new TestClass();
}
}
To #Grohl EDIT2:
It hurts to see that you are trying to read data without checking if there is any. In such cases, check!
Like this:
if(TEST.Count() >= 3)
{
MessageBox.Show(TEST[2].elNr.ToString());
}
It should debug at be smooth at runtime. I think your problem is getting the data.
Make sure you load the needed data and check if it isn't null.

How to fill the DataGridview Datasource with the List?

I have a List of string type in which I am storing some values and then inserting them into the database. Now I want to show those values into the Gridview when I fill my GridView data source with that List it only shows the total number of characters of each value in the list. Is there any procedure that I show the list values into the DataGridView.
My code below is as follows:
private void GenerateButton_Click(object sender, EventArgs e)
{
List<string> SerialNumberList = new List<string>();
int SerialNumberStart = Convert.ToInt32(Regex.Replace(StartSerialBox.Text, "[^0-9]+", string.Empty));
int SerialLimit = Convert.ToInt32(LimitBox.Text);
for (int i = 0; i < SerialLimit;i++ )
{
SerialNumberStart++;
SerialNumberList.Add("S" + SerialNumberStart);
}
for (int j = 0; j < SerialNumberList.Count;j++ )
{
Adapter.insertserialnumbers(SerialNumberList[j] , DateTime.Now.ToString()); //Insertiona Procedure which will save the values into the database.
}
SerialGridView.DataSource = SerialNumberList ;
}
you can use BindingList
for example :
protected void GenerateButton_Click(object sender, EventArgs e)
{
BindingList<ListType> SerialNumberList = new BindingList<ListType>();
int x = 5;
SerialNumberList.Add(new ListType(x.ToString()));
grid.DataSource = SerialNumberList;
grid.DataBind();
}
}
public class ListType
{
public ListType()
{ }
private string Itemname;
public ListType(string _ListItem)
{
ListItem = _ListItem;
}
public string ListItem
{
get { return Itemname; }
set { Itemname = value; }
}
}
You can add extention method for IEnumerable(here List) type object from this SO question. Use this extention method to create DataTable from SerialNumberList and bind to DGV like this:
SerialGridView.DataSource = SerialNumberList.ToDataTable();

color whole row instead of single cell

Ive been trying to change the background color of a row in the Compact Framework DataGrid and have found little success since the DataGrid on .NET CF is limited compared to its Windows Forms counterpart. My only bit of success in achieving my goal is I have now been able to change the background color of a single cell depending on its values. I couldnt manipulate the code I got from Googling since I am not that good in C#. However, this is the code that I have:
namespace GridColor
{
public delegate void CheckCellEventHandler(object sender, DataGridEnableEventArgs e);
public class DataGridEnableEventArgs : EventArgs
{
private int _column;
private int _row;
private bool _meetsCriteria;
public DataGridEnableEventArgs(int row, int col, bool val)
{
_row = row;
_column = col;
_meetsCriteria = val;
}
public int Column
{
get { return _column; }
set { _column = value; }
}
public int Row
{
get { return _row; }
set { _row = value; }
}
public bool MeetsCriteria
{
get { return _meetsCriteria; }
set { _meetsCriteria = value; }
}
}
public partial class ColumnStyle : DataGridTextBoxColumn
{
//public event CheckCellEventHandler CheckCellEquals;
public event CheckCellEventHandler CheckCellContains;
private int _col;
public ColumnStyle(int column)
{
_col = column;
}
protected override void Paint(Graphics g, Rectangle Bounds, CurrencyManager Source, int RowNum, Brush BackBrush, Brush ForeBrush, bool AlignToRight)
{
bool enabled = true;
if (CheckCellContains != null)
{
DataGridEnableEventArgs e = new DataGridEnableEventArgs(RowNum, _col, enabled);
CheckCellContains(this, e);
if (e.MeetsCriteria)
//g.DrawRectangle(new Pen(Color.Red, 2), Bounds.Y + 1, Bounds.Width - 2, Bounds.Height - 2);
BackBrush = new SolidBrush(Color.PaleGreen);
}
base.Paint(g, Bounds, Source, RowNum, BackBrush, ForeBrush, AlignToRight);
}
}
}
Now for my form, I have this:
namespace GridColor
{
public partial class Form1 : Form
{
DataSet ds;
SqlDataAdapter da;
private List<string> compareValues = new List<string>();
public Form1()
{
InitializeComponent();
try
{
addGridStyle(ref dataGrid1);
compareValues.Add("OK");
compareValues.Add("Filling");
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.ToString());
}
}
private void addGridStyle(ref DataGrid dg)
{
DataGridTableStyle dtStyle = new DataGridTableStyle();
dtStyle.MappingName = "Test";
string connString = "Data Source=192.168.2.16,1433;Initial Catalog=TestDB;User ID=sa;Password=ABC12abc;";
SqlConnection conn = new SqlConnection(connString);
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM Test";
ds = new DataSet();
da = new SqlDataAdapter(cmd);
da.Fill(ds, "Test");
for (int i = 0; i < ds.Tables["Test"].Columns.Count; i++)
{
ColumnStyle myStyle = new ColumnStyle(i);
myStyle.MappingName = ds.Tables["Test"].Columns[i].ToString();
if (i == 1)
{
if (ds.Tables["Test"].Columns[i].DataType == System.Type.GetType("System.String"))
myStyle.CheckCellContains += new CheckCellEventHandler(myStyle_CheckCellContains);
}
dtStyle.GridColumnStyles.Add(myStyle);
}
dg.TableStyles.Add(dtStyle);
}
public void myStyle_CheckCellContains(object sender, DataGridEnableEventArgs e)
{
try
{
if (compareValues.Contains((string)dataGrid1[e.Row, e.Column]))
e.MeetsCriteria = true;
else
e.MeetsCriteria = false;
}
catch (Exception ex)
{
e.MeetsCriteria = false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
dataGrid1.DataSource = ds.Tables["Test"];
}
}
}
In what part of my code should I change so that If a cell meets the criteria, its whole row will be colored instead of only it's own cell?
Alright I went back and found my code from years ago where I did this on the desktop, before the more advanced DataGridView came out, etc.
First of all there is this tutorial from Microsoft Customizing the Windows Forms DataGrid, which explains how to highlight an entire row.
I looked at my code and I had to add a custom column style for each column, fire an event to the main form which I handled, and then determined the proper color for that record. Then, I set the args.Color property and the DataGridColumn would draw the correct color. So yes, you have to actually have each column be your custom formatable class, then your application logic can handle the event, get the record data and determine the color
** Update: here's a simple example **
public partial class Form1 : Form
{
FormattableTextBoxColumn firstNameColumn = new FormattableTextBoxColumn();
FormattableTextBoxColumn lastNameColumn = new FormattableTextBoxColumn();
public Form1()
{
InitializeComponent();
// add first name col
firstNameColumn.MappingName = "FirstName";
dataGridTableStyle1.GridColumnStyles.Add(firstNameColumn);
firstNameColumn.SetCellFormat += new FormatCellEventHandler(ColumnSetCellFormat);
// add last name col
lastNameColumn.MappingName = "LastName";
lastNameColumn.SetCellFormat += new FormatCellEventHandler(ColumnSetCellFormat);
dataGridTableStyle1.GridColumnStyles.Add(lastNameColumn);
// This just sets up a dummy data source, since I don't have a database in this example
List<PersonTest> peopleList = new List<PersonTest>();
peopleList.Add(new PersonTest
{
FirstName = "Alan",
LastName = "QQQQQ",
HighlightPerson = true
});
peopleList.Add(new PersonTest
{
FirstName = "John",
LastName = "Smith",
HighlightPerson = false
});
BindingSource peopleDataSource = new BindingSource();
peopleDataSource.DataSource = peopleList;
dataGridTableStyle1.MappingName = peopleDataSource.GetListName(null);
dataGrid1.DataSource = peopleDataSource;
}
// I'll cache this brush in the form, just make sure to dispose it (see designer.cs disposing)
SolidBrush highlightBrush = new SolidBrush(Color.Yellow);
// here is the event you can handle to determine the color of your row!
private void ColumnSetCellFormat(object sender, DataGridFormatCellEventArgs e)
{
if ((e.Source.List[e.Row] as PersonTest).HighlightPerson)
e.BackBrush = highlightBrush;
}
// example test class
public class PersonTest
{
public String FirstName { get; set; }
public String LastName { get; set; }
public bool HighlightPerson { get; set; }
}
}
And the custom data grid column
public class FormattableTextBoxColumn : DataGridTextBoxColumn
{
public event FormatCellEventHandler SetCellFormat;
protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
{
DataGridFormatCellEventArgs e = new DataGridFormatCellEventArgs(rowNum, source);
e.ForeBrush = foreBrush;
e.BackBrush = backBrush;
OnSetCellFormat(e);
base.Paint(g, bounds, source, rowNum, e.BackBrush, e.ForeBrush, alignToRight);
}
private void OnSetCellFormat(DataGridFormatCellEventArgs e)
{
FormatCellEventHandler handler = SetCellFormat;
if (handler != null)
handler(this, e);
}
}
You'll also need this DataGridCellEventArgs.cs
public delegate void FormatCellEventHandler(object sender, DataGridFormatCellEventArgs e);
public class DataGridFormatCellEventArgs : EventArgs
{
public int Row;
public CurrencyManager Source;
public Brush BackBrush;
public Brush ForeBrush;
public DataGridFormatCellEventArgs(int row, CurrencyManager manager)
{
this.Row = row;
this.Source = manager;
}
}
Here's an example project for you:
DataGridTest.zip
I haven't worked with CF, but I thought I would throw this out there... If you can access the cell, wouldn't the row be it's NamingContainer? If so you could drill up to the row and apply a style or add an attribute with a CSS class.

Categories

Resources