Updating my database - c#

I am new with the subsonic, and I have a problem when trying to update the database from the sql server. I have created a gridview by still is not returning the updates results. can you please help me? its getting an error code on dc.AddMostaHse();
(Cannot implicity convert type 'void to 'object')
Here is the code being done of DataAccess.cs page
public void AddMostaHse()
{
Mosta.MostaHSE1 xx = new MostaHSE1();
xx.ID = 94;
xx.FunctionLocation = "lza94";
xx.acno = 12;
xx.Save();
}
Binding it with the gridview.
{
DataAccess dc = new DataAccess();
gvtest.DataSource = dc.AddMostaHse();
gvtest.DataBind();
}

This doesn't make much sense. Your gridview should be being bound from a Read operation. You are currently binding it to a Insert/Write operation based on what you have provided. You should probably be grabbing a collection of MostaHSE1() and displaying that in your gridview. The return type of your Read function should most likely be DataTable or DataSet.
Your AddMostHse1() appears it should work, but you want to target a different event off of the gridview to do this. Maybe RowEditEnding or some other event.

Your method AddMostaHse is returning void (no return). You cannot bind a datagrid to void. If you want to bind the datagrid to the object you just created in the method then change your method to:
public MostaHSE1 AddMostaHse() {
Mosta.MostaHSE1 xx = new MostaHSE1();
xx.ID = 94;
xx.FunctionLocation = "lza94";
xx.acno = 12;
xx.Save();
return xx;
}
It seems strange to me why you are binding one object to a datagrid (letting alone why would you bind a created object like that to a datagrid, I assume you are just testing), usually you bind a collection of objects..therefore this may not bring the result you want.
A more common candidate for your datagrid would be something like:
public IEnumerable<MostaHSE1> GetAllMostaHse() {
return Mosta.MostaHSE1.All();
}

Related

Data Binding with `List<T>`

I write a small program to record data change,it use a DataGridView,and it's datasource is a List, but I have a question on the DataBingding.
DataTable dataTable = GetBalance();
List<StockBalance> balances = ReadDataTable(dataTable);
List<StockBalance> stockBalances = (List<StockBalance>)dataGridView1.DataSource ?? new List<StockBalance>();
stockBalances.AddRange(balances);
dataGridView1.DataSource = stockBalances;
The above code can't refresh DataGridView, the data in balances will not show in DataGridView while stockBalances contains all new data, but the under code can archieveļ¼š
balances.AddRange(stockBalances);
dataGridView1.DataSource = balances;
I guess the reason is List and StockBalance is reference type,but I don't konw how to validate it, or it's not that?
Hope someone can help me, thanks.
A DataGridView - any bound control in fact - needs to receive a notification from the data source when the data changes in order to know that it needs to update. That requires an object that implements the IBindingList interface. The List<T> does not implement that interface and so the grid has no idea when data changes in the list and thus doesn't update.
What you should do is bind your list to a BindingSource and then bind that to the grid. In that case, when you make changes to the list you can then call an appropriate method of the BindingSource, e.g. ResetBindings, to provide an appropriate notification to the grid.
Note that, when I say "notification", I'm talking about an event. An IBindingList object raises its ListChanged event and the control handles that event.
You can do it using a Binding source:
var source = new BindingSource();
List<StockBalance> balances = ReadDataTable(dataTable);
List<StockBalance> stockBalances = (List<StockBalance>)dataGridView1.DataSource ?? new List<StockBalance>();
stockBalances.AddRange(balances);
source.DataSource = stockBalances;
dataGridView1.AutoGenerateColumns=true;
dataGridView1.DataSource = source;

Browsable(false) at run time?

I am using a datasource to populate my datagridview with the data. However, im trying to find a way for the user to be able to hide columns that he does not want to see.
I am able to hide and show columns before the program runs using:
[Browsable(false)]
public string URL
{
get
{
return this._URL;
}
set
{
this._URL = value;
this.RaisePropertyChnaged("URL");
}
}
I cannot seem to figure out how to change the [Browsable(false)] at run time.
Any ideas how I could accomplish this?
Basically, I want to bind an "on/off" to a menu.
Apologies if im not using the right terminology when explaining my problem, I am self taught and started a few weeks ago - so still very newbie :)
Edit:
Cant hide the column because when i run my update function all columns appear again. Here is my function for updating:
private void UpdateResults()
{
Invoke(new MethodInvoker(
delegate
{
this.dgvResults.SuspendLayout();
this.dgvResults.DataSource = null;
this.dgvResults.DataSource = this._mySource;
this.dgvResults.ResumeLayout();
this.dgvResults.Refresh();
}
));
}
At run time, you can just specify the column as being invisible:
dgv.Columns["ColumnName"].Visible = false;
The way to do this properly at runtime is to provide a custom ITypedList implementation on the collection, or provide a TypeDescriptionProvider for the type, or (for single-object bindings, not lists), to implement ICustomTypeDescriptor. Additionally, you would need to provide your own filtered PropertyDescriptor implementation. Is it really worth it? In most cases: no. It is much easier to configure the grid properly, showing (or not) the appropriate columns by simply choosing which to add.
Indeed, as others had mention the purpose of BrowsableAttribute is different, but I understand what you want to do:
Let's suppose that we want to create a UserControl than wraps a DataGridView and gives the user the ability to select which columns to display, allowing for complete runtime binding. A simple design would be like this (I'm using a ToolStrip, but you can always use a MenuStrip if that's what you want):
private void BindingSource_ListChanged(object sender, ListChangedEventArgs e) {
this.countLabel.Text = string.Format("Count={0}", this.bindingSource.Count);
this.columnsToolStripButton.DropDownItems.Clear();
this.columnsToolStripButton.DropDownItems.AddRange(
(from c in this.dataGrid.Columns.Cast<DataGridViewColumn>()
select new Func<ToolStripMenuItem, ToolStripMenuItem>(
i => {
i.CheckedChanged += (o1, e2) => this.dataGrid.Columns[i.Text].Visible = i.Checked;
return i;
})(
new ToolStripMenuItem {
Checked = true,
CheckOnClick = true,
Text = c.HeaderText
})).ToArray());
}
In this case, bindingSource is the intermediary DataSource of the dataGrid instance, and I'm responding to changes in bindingSource.ListChanged.

Why does the DataGrid not update when the ItemsSource is changed?

I have a datagrid in my wpf application and I have a simple problem. I have a generic list and I want to bind this collection to my datagrid data source every time an object is being added to the collection. and I'm not interested to use observable collection.
the point is I'm using the same method somewhere else and that works fine. but this time when i press Add button an object is added and datagrid updates correctly but from the second item added to collection datagrid does not update anymore.
Here is the Code :
private void btnAddItem_Click(object sender, RoutedEventArgs e)
{
OrderDetailObjects.Add(new OrderDetailObject
{
Price = currentitem.Price.Value,
Quantity = int.Parse(txtQuantity.Text),
Title = currentitem.DisplayName,
TotalPrice = currentitem.Price.Value * int.Parse(txtQuantity.Text)
});
dgOrderDetail.ItemsSource = OrderDetailObjects;
dgOrderDetail.UpdateLayout();
}
any idea ?
The ItemsSource is always the same, a reference to your collection, no change, no update. You could null it out before:
dgOrderDetail.ItemsSource = null;
dgOrderDetail.ItemsSource = OrderDetailObjects;
Alternatively you could also just refresh the Items:
dgOrderDetail.ItemsSource = OrderDetailObjects; //Preferably do this somewhere else, not in the add method.
dgOrderDetail.Items.Refresh();
I do not think you actually want to call UpdateLayout there...
(Refusing to use an ObservableCollection is not quite a good idea)
I also found that just doing
dgOrderDetails.Items.Refresh();
would also accomplish the same behavior.
If you bind the ItemSource to a filtered list with for example Lambda its not updated.
Use ICollectionView to solve this problem (Comment dont work):
//WindowMain.tvTemplateSolutions.ItemsSource = this.Context.Solutions.Local.Where(obj=>obj.IsTemplate); // templates
ICollectionView viewTemplateSolution = CollectionViewSource.GetDefaultView(this.Context.Solutions.Local);
viewTemplateSolution.SortDescriptions.Clear();
viewTemplateSolution.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
viewTemplateSolution.Filter = obj =>
{
Solution solution = (Solution) obj;
return solution.IsTemplate;
};
WindowMain.tvTemplateSolutions.ItemsSource = viewTemplateSolution;
i use ObservableCollection as my items collection and than in the view model
call CollectionViewSource.GetDefaultView(my_collection).Refresh();

Can't refresh datagridview with bindingsource

Goal:
Once clicking on add or delete button, the datagridview should be refreshed with the latest data from document.
Problem:
The datagridview can't be refreshed
after making changes by deleting or
adding new data.
I'm using binding source that is linked with datagridview's datasource.
I tried everything with different solution and read advise from different forum but still I can't solve this problem.
I also tried using these syntax "BindingSource.ResetBindings(false)", "BindingSource.Refresh()" etc but no result.
Links below:
How to refresh a bindingsource
http://www.eggheadcafe.com/community/aspnet/2/10114324/datagridview-refresh-from-another-form.aspx
http://blogs.msdn.com/b/dchandnani/archive/2005/03/15/396387.aspx
http://bytes.com/topic/c-sharp/answers/812061-problem-refresh-datagridview
bSrcStock.DataSource = myProductrepository.GetAllProductList();
dgridStock.DataSource = null;
dgridStock.DataSource = bSrcStock;
bSrcStock.ResetBindings(true);
dgridStock.Columns[0].Width = 101;
dgridStock.Columns[1].Width = 65;
dgridStock.Columns[2].Width = 80;
dgridStock.Columns[3].Width = 120;
dgridStock.Columns[4].Width = 90;
I have faced this same issue and found out that the problem is with the initialization of the BindingSource inside a static constructor (The class was a singleton). Upon realizing this, I moved the code to the calling event and it finally worked without needing to assign null or call the clear method. Hope this helps.
No need to define the columns (unless you really want to...)
Then just call for the refreshDataGridView Method every time you add or remove something from your list...
public List<CustomItem> ciList = new List<CustomItem>();
CustomItem tempItem = new CustomItem();
tempItem.Name = "Test Name";
ciList.add(tempItem);
refreshDataGridView();
private void refreshDataGridView()
{
dataGridView1.DataSource = typeof(List<>);
dataGridView1.DataSource = ciList;
dataGridView1.AutoResizeColumns();
dataGridView1.Refresh();
}
You need a list that will inform the BindingSource when an item is added etc. Use a System.ComponentModel.BindingList for that.
Dim lisItems As New System.ComponentModel.BindingList(Of myObject)
Works Great! Only AddRange is missing so this takes care of that:
Private Sub AddRange(ByVal lis As List(Of myObject))
For Each itm In lis
lisItems.Add(itm)
Next
End Sub
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.bindinglist-1?view=netframework-4.7.2

DataGridView does not display DataTable

I've got the following code which I think ought to be binding a DataTable to a DataGridView, but the DataGridView shows up empty. The DataTable definately has rows, so I assume that I am binding the DataSource incorrectly some how. Does anyone see what is wrong with this:
DataBase db = new DataBase(re.OutputDir+"\\Matches.db");
MatchDBReader reader = new MatchDBReader(db.NewConnection());
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = reader.GetDataTable();
this.dataGridView1.DataSource = bindingSource.DataSource;
The first line simply gets a handle to the DB that I'm pulling data from.
The next line is a provides a class for reading from that same db - in particular it exposes the GetDataTable method with returns the data table that I intend to put into the DataGridView.
The next line is uninteresting...
The 4th line attempts to grab the DataTable - QuickWatch indicates that this is working...
The final line is where I assume i've screwed up...my understanding is that this binds the DataTable to the DataGridView GUI, but nothing shows up.
Any thoughts?
Try binding the DataGridView directly to the BindingSource, and not the BindingSource's DataSource:
this.dataGridView1.DataSource = bindingSource;
You need to attach your BindingSource to your grid, before you get the data table.
Try switching the last two lines of code:
DataBase db = new DataBase(re.OutputDir+"\\Matches.db");
MatchDBReader reader = new MatchDBReader(db.NewConnection());
BindingSource bindingSource = new BindingSource();
this.dataGridView1.DataSource = bindingSource.DataSource;
bindingSource.DataSource = reader.GetDataTable();
Along with above solutions also fix the "bindingSource" datamember property. like:
bindingSource.DataMember = yourDataSet.DataTable;
I had the same problem with sql database and datagrid view. After a great deal of trouble I found out that I've forgot to set dataMember property of my binding source.
best of luck.
None of this worked for me, though it all seemed like good advice. What I ended up doing was the biggest, worst hack on earth. What I was hoping to accomplish was simply to load a DB table from a SQLite db and present it (read only, with sortable columns) in the DataGridView. The actual DB would be programmatically specified at runtime. I defined the DataSet by adding a DataGridView to the form and used the Wizards to statically define the DB connection string. Then I went into the Settings.Designer.cs file and added a set accessor to the DB Connection string property:
namespace FormatDetector.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("data source=E:\\workspace\\Test\\Matches.db;useutf16encoding=True")]
public string MatchesConnectionString {
get {
return ((string)(this["MatchesConnectionString"]));
}
set
{
(this["MatchesConnectionString"]) = value;
}
}
}
}
This is a klugey hack, but it works. Suggestions about how to clean this mess up are more than welcome.
brian
DataGridView takes a DataTable as a basis. The DataTable Columns save their Type as a property.
If this type is an Interface all you would see are empty cells.

Categories

Resources