This question may sound trivial but I'll ask it anyway. Given code below, what is the proper way to force ListBox to reflect new table content.
SQLDataContext dataContext = new SQLDataContext();
BindingDataSource myBindingDataSource = dataContext.MyTable1;
listBox1.DataSource = myBindingDataSource;
listBox1.DispalyMember = "Column1";
listBox.ValueMember = "Column2";
MyTable1 newRecord = new MyTable1();
newRecord.Column1 = "Some data";
newRecord.Column2 = 123;
dataContext.MyTable1.InsertOnSubmit(newRecord);
dataContext.SubmitChanges();
What is the most efficient way or best practice if you prefer, to force listBox1 into reflecting dataContext changes?
Please do not get offended but this is a classic example of misusing collections. You are using 2 parallel collections and you can't expect one to know much about one another unles they are properly linked. Since you are binding listBox1 to BindingDataSource you should perform add, remove and update operations on the same BindingDataSource. It binds both ways. Everything you add, update or delete from it will be reflected in bound controls and in the context. Just submit context changes and you will update the database. In your example, you bypass BindingDataSource and write directly to the context so `BindingDataSource' has no idea about the change.
Related
I'm new here this is my first question and I beforehand apologize for any lack of information, search or tags in the post or anything at all.
I'm writing a pretty simple winforms program, and I'm having problems with cascading combo boxes, pretty much like country>Estate>City I'm new to this, I'm using Entity Framework and I'm getting by with something like this:
private void Form_CadAnimal_Load(object sender, EventArgs e)
{
using (DbClinvetEntities ctx = new DbClinvetEntities())
{
cmb_especie.DataSource = ctx.Especie;
cmb_especie.DisplayMember = "Nome";
cmb_especie.ValueMember = "EspecieID"
cmb_raca.DataSource = ctx.raca;
cmb_raca.DisplayMember = "Nome";
cmb_raca.ValueMember = "RacaID";
}
}
So far so good all is going ok, I get them to be populated, I've found countless posts on the matter, but perhaps for lack of knowledge I could not relate them to my situation.
now all I would like to do is filter cmb_Raca by the value selected in cmb_Especie, just to make it clearer Raca table has a foreign key on Especie table, pretty much like you would expect country>estate to be.
I've found posts where a new context is generated on SelectedIndexChanged and a whole new binding is done, but I wonder if there is a way to make this work without making further calls to the Db, any way to take the list of objects and work them offline after the first access?
Sorry if this is anyhow unclear, I'll glady edit the post to provide further information if necessary.
try using the SelectedIndex as your query select command.you can build a module for talking to the database that takes the SelectedIndex.ToString() as a parameter to build your Query and fill data to your form based on that. the Combobox doesn't necessarily have to be databound when it is used that way.
I have multiple DropDown-style ComboBoxes on a form in which the user is able to specify which units are associated with a value (think meters, feet, etc.). To do this, I use an application string collection in Settings.Settings with some default unit types which is bound to the DataSource of the ComboBox as follows:
this.cboUnit.DataSource =
(System.Collections.Specialized.StringCollection)Properties.Settings.Default.Units;
The user is able to successfully pick a unit or specify a new one.
Now, when I save this.cboUnit.Text into some XML profile, I am able to handle both cases. Opening the XML profile and performing this.cboUnit.Text = "NonExistentUnit"; will fail and cause the first item in the collection to be selected instead.
How can I modify the ComboBox to support the kind of behavior I'm asking, without adding the item to the ComboBox or modifying the DataSource itself?
There was a solution suggested in Using ComboBox.Text when combobox is tied to DataSource but I couldn't find official documentation to support this behavior. For that reason I prefer to avoid it.
I could not find any valid way to insert items into a bound DataSource. So instead I ended up doing the following:
BindingSource bindingSource = new BindingSource((System.Collections.Specialized.StringCollection)Properties.Settings.Default.Units, "");
if(!bindingSource.Contains(someSavedValue))
{
bindingSource.Insert(0, someSavedValue));
}
this.cboUnit.DataSource = bindingSource;
This creates a new instance of the binding source that can be modified prior to binding it to a data source. I wrapped this code in a method for which I can pass in a string collection and the stored value (savedUnit in this case) that returns a new BindingSource instance. This is especially useful in my case, as I can now simply write:
this.cboLengthUnit.DataSource = CreateBindingSource(unitsCollection, savedLengthUnit);
this.cboWidthUnit.DataSource = CreateBindingSource(unitsCollection, savedWidthUnit);
this.cboHeightUnit.DataSource = CreateBindingSource(unitsCollection, savedHeightUnit);
I wrote the code above from memory, so it may contain a mistake.
BlaEntities TestContext = new BlaEntities();
IQueryable<TestEntity> Entities = TestContext.TestEntity;
TestDataGridView.DataSource = Entities;
When I assign Entities to TestDataGridView's DataSource directly; I don't have to do anything to reflect my changes to the grid.
TestEntity entity = Entities.First();
entity.Title = "What up!?";
This is more than enough to see the change in the TestDataGridView. One exception I encountered was that if I add another row to the TestContext using TestContext.AddToTestEntity(...) , it doesn't show up in the grid (contrary to deleting it) but I got it working using the BindingSource's Add method.
BindingSource source = new BindingSource{DataSource = Entities};
TestDataGridView.DataSource = source;
source.Add(CreateNewTestEntity());
Now the only obstacle left in my way is this:
If I use filtering - like TestContext.Where(t => t.Active) - use it as DataSource to my grid, then change the first record's Active property to false, how do I refresh/reload the grid to reflect this without creating another instance of BlaEntities?
IQueryable<TestEntity> FilteredEntities =
TestContext.TestEntity.Where(t => t.Active);
TestDataGridView.DataSource = FilteredEntities;
TestEntity temp = FilteredEntities.First();
temp.Active = false;
I see it is not active anymore in grid but since the grid should show only the active records, how can I remove it from the grid without removing it from the source?
When I iterate over FilteredEntities, I can see that the temp isn't there anymore but I still can see and edit it in the grid. So what I need is something forces grid to iterate its DataSource (which is FilteredEntities) as well and populate itself again
I tried calling TestContext's Refresh method and BindingSource's reset methods.
I tried changing TestDataGrid.DataSource to null, then changing it back to FilteredEntities hoping to re-populate the rows, didn't work either.
It works if I save my changes using TestContext.SaveChanges() and use another instance of BlaEntities like TestDataGridView.DataSource = new BlaEntities().TestEntity.Where(t => t.Active) but I need to use my current instance.
So the question is, how can I make the TestGridView to reload its contents using FilteredEntities.
Any advice would be greatly appreciated. Thank you.
since you already have a BindingSource have a look at the ResetBindings method
//edit:
as from the comments below:
i would approach this problem with a factory for "Entities" ... if that factory would hold a ref to the last created IQueryable, it could implement the interface IQueryable itself, by forwarding all interface methods to that created object ... so it could act as a wrapper for your datasource that can replace that datasource by recreating it based on the predicate function and the actual state of all objects
First let me start by explaining my use case:
Say there is a database "Cars". In that database, each row might have Make, Model, EngineType, etc. I have a page that is essentially a view of a single "Car" record, displaying its various stats. In that page, I have a user control that calculates and displys various MPG stats based on the "Car" record. The user control is passed the "Car" record via a property, then uses it internally for its calculations.
Inside that user control, something like this happens:
private void DataBindGrid()
{
gridView.DataSource = this.CarRecord.GetMPGStats();
}
Internal to "CarRecord", is a LINQ-to-SQL query, using the data context of CarRecord. For the purpose of this calculation, it would be more efficient to do this:
private void DataBindGrid()
{
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Car>(c => c.Engine);
this.CarRecord.DataContext.LoadOptions = dlo;
gridView.DataSource = this.CarRecord.GetMPGStats();
}
For the purpose of this example, ignore whether or not this may be a bad design for a user control passing in a record & datacontext.
Here are the issues I'm seeing:
The page may have set its own load options before passing the record to the user control, resulting in an inefficient query.
The page may not want the new settings specified by the user control when it continues to use the Car record itself.
So I have two questions:
What is the best way to "clear" LoadOptions? Simply set DataContext.LoadOptions = new DataLoadOptions(); or = null;?
Is there any way to set some sort of temporary LoadOptions that only affect a certain operation before reverting to whatever they were before?
Thanks in advance.
data load options always have to be set before execution of first query. once a query executes there is nothing u can do with them.
I use a DeatialsView with AutoGeberateColoums for my user administration.
Here my start code:
Business.UserHandling uh = new Business.UserHandling();
DAL.Benutzer user = uh.GetSingleUser(BenutzerID_Int);
List<DAL.Benutzer> listUser = new List<DAL.Benutzer>();
listUser.Add(user);
DetailsView1.DataSource = listUser;
DetailsView1.DataBind();
How can I save it automaticly without must assigning every field from the view to an object field?
Please be aware, I have different projects to cut the ASP-Layer from the Data Layer, so I must only have an "Benutzer"-Object, I can't use LinQ directly here.
(P.s.: I musst add the "Benutzer"-Object to a list, because the DetailsView won't have a single object, if someone knows it better, please correct me).
try to bind your detailsview to linqdatasource and it will automatically update linq object