I have developed a form in c# which is called inside a console application.
Below is how i have called the form inside the console.
Application.Run(new Form1(display_list));
displaylist is a list of struct
List , form_columns is a struct consisting of 3 string values which needs to be displayed side by side in a datagrid.
Below is the constructor of the form
public Form1(List<form_columns> disp)
{
InitializeComponent();
BindingSource source = new BindingSource();
source.DataSource = disp;
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = source;
}
But when the program is run , the datagridview is empty. it is not showing any data .
What mistake am i making?????
Try to bind the list using BindingList
BindingList<form_columns> bl = new BindingList<form_columns>(disp);
BindingSource source = new BindingSource(bl, null);
//source.DataSource = disp;
Related
I have a base form in where I populate a combox with the following code:
private void FillComboBoxItemsFromResources(ComboBox comboBox, bool firstIsEmpty, bool selectFirst)
{
var res = new Resources(System.Threading.Thread.CurrentThread.CurrentCulture);
var cbEntries = res.GetComboBoxItems(comboBox.Name);
if (firstIsEmpty)
{
cbEntries[0] = new KeyValuePair<int, string>(0, string.Empty);
}
comboBox.DataSource = cbEntries.ToArray();
comboBox.DisplayMember = "Value";
comboBox.ValueMember = "Key";
if (selectFirst && cbEntries.Count > 0)
{
comboBox.SelectedIndex = 0;
}
}
When I run the code and show the base form. -> All works.
When I inherit another form from my base form the code compiles but crashes with "Items-Collection cannot be modified when the data source is set" in Windows form designer generated code.
How to work around this ?
Any help is highly aprreciated.
TIA acki
Well after hours of trying around with rebuilding base form, rebuilding inherited form I just deleted the combobox in base form. Readded combobox into base form, uncommented code to fill combobox and now it works all as expected...
A brief intro
The program runs a test on the machines. Then a dialogBox appears asking the user if all the machines worked correctly. If they say no another window appears with the dataGridView asking which machines failed through the checkBox method. This then sets the status to the ERROR status so the program can continue running while ignoring the machines with errors.
I have this class with the two properties
public class ASM
{
public byte DeviceID
public ASMStatus Status
}
I put this in a list
list<ASM001.ASM> ASMs = new list();
Now I want to add this list to a bindingSource in my dataGridView but only those whose Status equals ASMStatus.IDLE
I thought about just creating those that have idle into another list and attaching that to the binding list, however, the dataGridView also has a checkBox column that determines if the status needs to be changed to ASMStatus.ERROR
public partial class FailedMessageBox : Form
{
public FailedMessageBox()
{
InitializeComponent();
DataGridViewCheckBoxColumn col1 = new DataGridViewCheckBoxColumn();
col1.HeaderText = "Device Failed";
dataGridView1.Columns.Add(col1);
}
private void FailedMessageBox_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = Global.ASMs;
}
}
I want to make sure that when the user clicks OK the current ASMs in the list get set to ERROR which is why I thought a bindinglist would work the best
I am wondering if there was a quick way to do this or if I just have to do a bunch of loops.
What about something similar in your Page_load:
using(var context = new DbContext())
{
// You could put a Where Clause here to limit the returns
// i.e. context.ASMs.Where(s => s.Status == ASMStatus.IDLE).Load()
context.ASMs.Load();
var data = context.ASMs.Local.ToBindingList();
var bs = new BindingSource();
bs.DataSource = data;
dataGridView1.DataSource = bs;
}
You should add a BindingSource directly to the page but I am just showing adding it in code. Then you can access it like this:
foreach(DataRow row in dataGridView1.Rows)
{
if ((bool) row.Cells["Device Failed"].Value == true)
{
var line = row.DataBoundItem();
line.Status = ASMStatus.ERROR;
}
}
Make sure you save the changes.
I have tow form,ListFrom, and DetailForm
In the ListForm I have a devexpress grid and some button(add, delete, edit)
In the DetailForm I have some textboxes and some button(save,delete,next,previous)
well I have to senario
1 - I open the ListForm and I click on a product to modify it a got the DetailForm opened, I make some modification and I save,then i should have my grid in the ListForm refreshed with the new value.for this I have this code
In the ListFrom
FrmProduit frm = new FrmProduit(monProduit.Id) { MdiParent = this.MdiParent};
frm.updateDataInGridView += new System.Action(refereshGridView);
frm.Show();
in the detailform
if (updateDataInGridView != null)
updateDataInGridView();
well in this scenario everything is OK
second scenario
If I open the detailFrom,and after that I open the listForm, I make some change in the detailFrom and I click save updateDataInGridView in this case is null and then the grid is not refreshed
anyone have suggestion?
I would create a shared BindingSource that both forms would use to show data. If any item is changed in BindingSource it takes care to notify all controls bind to it and so it would refresh grid automatically.
Second approach is to make refereshGridView method public and in DetailForm on save click do this:
var lists = Application.OpenForms.OfType<Form>().Where(x => x.GetType() == typeof(ListFrom));
foreach (var listform in lists)
{
listform.refereshGridView();
}
I did not use FirstOrDefault as maybe there is more than one listform opened.
EDIT about Binding Source
Here is quite good tutorial so please take a look.
Below is a fast-written far from best example of stretch I did:
internal static class DataSources
{
private static BindingSource bs;
public static BindingSource CerateDataSource(List<object> yourObjects)
{
bs = new BindingSource();
bs.DataSource = yourObjects;
}
public static BindingSource GetDataSource()
{
return bs;
}
public static void Reset()
{
bs.ResetBindings(false);
}
}
and then in your listview
dataGridView1.DataSource = DataSources.GetData();
and in detailsview where you are editing one of the objects from BindingSource on save you would have to call: DataSources.Reset();. This is just a markup, but hopefully you get the idea :).
You must always be sure you are referring to the current instance of detailform, thus declare on your listForm
detailform obj = (detailform)Application.OpenForms["detailform"];
And every time you call detailform from listForm do it by obj e.g:
obj.Show()
This is the section of the form I am working on:
The following code links the BindingNavigator to the dataset using a bindingSource. Can I use this binding source to hook up the two text boxes to the data?
Do I simply need to use a property of the textboxes or is this more involved?
i.e when the form loads the first record's fields "Work Phrase" and "Description" will be displayed and when I scroll using the navigator the values in these boxes will change accordingly.
public partial class uxRevisionHelperForm : Form
{
public SqlCeConnection conn = new SqlCeConnection(ConfigurationManager.ConnectionStrings["WindFormAppRevisionHelper.Properties.Settings.DefinitionsDBConnectionString"].ConnectionString);
BindingSource definitionsBindingSource = new BindingSource();
public uxRevisionHelperForm()
{
InitializeComponent();
uxDescriptionTextBox.AutoSize = true;
this.hookUpBindingNavigator();
}
public void hookUpBindingNavigator()
{
SqlCeDataAdapter da = new SqlCeDataAdapter(new SqlCeCommand("Select * From tb_Definitions",conn));
DataSet ds = new DataSet("Helper");
ds.Tables.Add("DefinitionsTable");
da.Fill(ds.Tables["DefinitionsTable"]);
// Assign the BindingSource.
this.uxBindingNavigator.BindingSource = this.definitionsBindingSource;
this.definitionsBindingSource.DataSource = ds.Tables["DefinitionsTable"];
}
Try using the DataBinding collection of the textboxes.
Something like this:
uxDescriptionTextBox.DataBindings.Add("Text",
definitionsBindingSource,
fieldInTable);
Have added the full source code (highlighting exactly your requirement) here - http://sdrv.ms/NyXHdu. Download > Open the solution in VS2010 > Hit F5
[Update]
Double click on Form.cs designer and observe the productListBindingSource. It bound to a custom object - The ProductList class
Then see the properties of the TextBoxes & ComboBox and observe the DataBindings > Text property. They are bound to the productListBindingSource's individual item. See Image below.
Courtsey - http://www.apress.com/9781590594391/ [Chapter 8]
I have a couple of ComboBoxes on a Win Form that I always set list to the DataSource like this:
aComboBox.DataSource = someList;
foreach(Object obj in aComboBox.Items) {
// do something
}
This works perfectly fine for me, however, I have some trouble when trying to reset the data like this:
aComboBox.DataSource = null;
aComboBox.DataSource = someOtherList;
foreach(Object obj in aComboBox.Items) {
// do something else
}
The DataSource is reset successfully, but that does not trigger to reset the Items. I tried to call aComboBox.Items.Clear() to clean up the Items, no resetting happened.
Have I missed something?
Looks like that is all because of the form is "owned" by another form, where I have it child.Show(this) in the parent form to have the convenient to access methods from the parent form in the child.
In addition, using the BindingSource to look after the data binding will do the trick. This is what I've done:
BindingSource bs = new BindingSource;
aComboBox.DataSource = bs;
bs.DataSource = someList;
//
// after some processing
//
bs.DataSource = null;
bs.DataSource = someOtherList;
Try steps in this sequence
cmbBox.Items.Clear();
cmbBox.DataSource = SomeOtherList;
cmbBox.DataBind();