i am new to infragistics and to winGrids
I have SQL database with the following table
Costumers
[ID][Name]
In addition , i have UserControl which has winGrid and add\remove buttons.
When the UserControll becomes, active winGrid datasource is bounded to the table
winGrd.DataSource = Tables.Costumers;
When user wants to add\remove data from costumers table he clicks the relevant button.
The table is changed accordingly but the displayed data in the grid is not changed.
I used
winGrd.Refresh();
but it does no effect
what is the way to do this, Code examples are welcome
thanks
---Edited ----
Adding code:
private void BtnAdd_Click(object sender, System.EventArgs e)
{
//...
DB.DataProxy.AddCostumer(txtType.Text);
winGrd.Refresh();
//...
}
AddCostumer method eventually calls for the following method that updates the costumer table
public void AddCostumer(string type)
{
Costumers.InsertOnSubmit(new InsertOnSubmit{ Name = name});
}
If your DataTable is being updated, the UltraGrid should be showing those changes for you. What you could try is to call
ultraGrid1.Rows.Refresh(Infragistics.Win.UltraWinGrid.RefreshRow.ReloadData);
or
ultraGrid1.Rows.Refresh(Infragistics.Win.UltraWinGrid.RefreshRow.RefreshDisplay);
Not sure, but, as from MSDN documentation on InsertOnSubmit()
The added entity will not appear in query results from this table until after SubmitChanges has been called.
So, perhaps, if you want the result appear immediately in the Costomers entity and then in the WinGrid, you should call, in the code above the SubmitChanges()
public void AddCostumer(string name)
{
Costumers.InsertOnSubmit(new Costumers() { Name = name});
// Submit the change to the database.
try
{
db.SubmitChanges();
}
catch (Exception e)
{
// message to the user???
}
}
Once you executed the add/remove command, re-pull the data from database and redo the binding. Set the DataGridView.DataSource to null before all that, just in case; you wouldn't want to display wrong data if the connection or any other database-related process fails.
I think it's because you are setting a DataSource that doesn't implements IBindableList which UltraGrid uses for automatically update data it changes.
You could try refreshing it manually setting DataSource to null and resetting DataSource again when you need to show new info.
Related
I am in this situtation : view image
there are 5 user controls stacked in the empty panel.
I have a vertical menu in which there are several buttons and when I click on a button, I use : BringToFront() for displaying them .
private void Button1_Click(object sender, EventArgs e)
{
tabRandom1.BringToFront();
}
each usercontrol contains datagridview, and other elements that have to be loaded with the data coming from database, but I would like that if I click on button1, only that the elements of usercontrol1 be loaded .
when i tried :
private async void UserControl1_Load(object sender, EventArgs e)
{
this.DataGridView1.DataSource = await GetDataAsync();
}
i get a exception #er-shoaib :
there is already an open DataReader associated with tis connection which must be closed first.
I am looking for the best way to load the elements of the active usercontrol
Error you are getting is clearly saying you have already opened DataReader.
You cannot have more than one opened DataReader inside one connection.
In order to make your code for communication with database more stable write code with using and it will automatically dispose of objects like this:
using(SqlConnection con = new SqlConnection("..."))
{
con.Open();
using(SqlCommand cmd = new SqlCommand("...", con))
{
using(SqlDataReader dr = cmd.ExecuteReader())
{
while(dr.Read())
// Do the things
}
}
// Do not need close since connection will be disposed
}
or if you opened one connection for let's say whole class (like i think you did up there) just do not wrap SqlConnection con = new Sql.... inside using but everything others do and you will have no problem expect do not forget to do connection.Close().
I am ALWAYS using using for every component in sql connection and it is not affecting my performance.
When you reorganize code this way you will get rid of that problem, but one advice is not to load data when someone open form since you will load it 5 times and user may use only one but better create method like RefreshData() inside your UC and before you do yourUserControl.BringToFront(); you also do yourUserControl.RefreshData() and this way you will load it only if needed and you will always have fresh one plus you will have easy method for refreshing data if needed anywhere.
void OnDependencyChange(object sender,SqlNotificationEventArgs e)
{
MessageBox.Show("changed");
}
I'm running a query in ViewModel, I get the result (Let's say 10). If I try to insert instantly to SQL a new row, I don't the MessageBox. However, If I stop debugging and re-run my application, It will show as If the value changed which it did. Isn't SQLDependency supposed to give you real time notifications?
I was expecting the MessageBox to show the minute I add a new row in my table.
My project have a MainForm, i show F_Insert and set MdiParent for MainForm
F_Insert f = new F_Insert();
f.MdiParent = this;
f.Show();
In F_Insert, i put a button with CLick event like this
private void btn_Add_Click(object sender, EventArgs e)
{
//Insert data to SQL
}
Besides, i want to auto upload data that inserted from F_Insert every 5 second
I use System.Timer.Timer and set it to Thread in MainForm_Load
Thread t1 = new Thread(new ThreadStart(Timerss)); //In MainFormLoad event
t1.Start();
public void Timerss()
{
System.Timers.Timer timer = new System.Timers.Timer(5000);
timer.Elapsed += Timer_Insert_Tick;
timer.AutoReset = true;
timer.Start();
}
private static void Timer_Insert_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
//code auto upload data to server here
//Data get from Sql Local to upload SQL in Server
}
The problem is it's not working good. I feel when i insert data form F_Insert, data is affected by Timerss thread that i start in MainForm load.
The simple way to show you my problem: when i split two work (Insert
and upload) into 2 difference work, it working good, it's mean i'm
insert data complete and then, i upload data, it will working good.
But when i insert data and data auto upload by timer in the same time,
i see some error that: conection sql close or open error, no data get
from F_Insert, sometime it get duplicate data (old data)
Please suggeted me some idea for this problem. Sorry but i'm newbie in thread. Thank you !!!
Well depending on what you trying to do this code should be modified but i hope it'll give you starting point to work with.
First of all let's create static field:
static volatile bool isDataChanged;
Keyword volatile makes this bool thread-safe, it means that this field always holds latest (and therefore correct) value when it is accessed by any thread in multi-thread environment).
We need this field to hold bool value that is used later to check whether the data was modified or not.
Assuming that data is modified inside click event handler, we should set this flag to true :
private void btn_Add_Click(object sender, EventArgs e)
{
// Data is modified in UI thread
isDataChanged = true;
}
Then let's assume that in Timer tick event we should upload the latest data to database (data is located in UI thread and could change in time span in between two tick events).
First of all we check if there is any changes to our data and if there's not we just exits the method. If changes was done we need to upload them to DB and in order to do so we have to deal with the fact that data in Timer thread could very well not be the same as data in our UI thread.
Let's create local variable that will hold correct data that we fetch from UI thread and use this.Invoke() to invoke Func<object> delegate on UI thread. The method that is attached to delegate returns instance of correct data retrieved from UI thread as object. We cast it explicitly to the type that our data is (usually it's one of collection types like List<T> or Dictionary<T1, T2>) and use this data to upload it to the DB.
After that, because our data in DB is the correct one, we change flag isDataChanged to false.
private void Timer_Insert_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
if(!isDataChanged) return;
// A very important line. It gets data from UI thread before uploading it
// Change DataType with your data Type and dataToUpload with data instance
DataType data = (DataType)this.Invoke(new Func<object>(() => dataToUpload));
//use data to upload your data to server
isDataChanged = false;
}
P.S.
Also it is better to place reference to our Timer in outer scope (so it can be accessed from anywhere inside the form)
public partial class MyForm : Form
{
...
System.Timers.Timer timer;
public void Timerss()
{
timer = new System.Timers.Timer(5000);
}
...
}
Dictionary<string, string> propertyCompany = new Dictionary<string, string>();//gloabal variable
protected void Page_Load(object sender, EventArgs e)
{
if(!isPostBack){
propertyCompany .add("a","1");
propertyCompany .add("b","2");
propertyCompany .add("c","3");
}
}
protected void btnGetProperty_Click(object sender, EventArgs e)
{
string a=propertyCompany["a"];//error this key is not exist
//propertyCompany is null
}
when define a propertyCompany and fill in form_load. in on click button propertyCompany is null!?
i use a static but i does not understand sometime say error is null.
Each request creates new page object, therefore you cannot use in second request (bnt click) dictionary you have created in first request (load without postback)
Remove test for postback for quick fix.
Other fix posibilities:
* store dictionary in viewstate.
Every variable defined in a class inheriting Web.UI.Page will be destroyed at the end of the Page-Lifecycle, hence it will be null in a Postback if you don't reinitialize it.
One way to persist it across postbacks is to store it in a Session-variable.
You will find a complete list of all options on how to persist variables across postbacks here: http://msdn.microsoft.com/en-us/magazine/cc300437.aspx
Application
Cookies
Form Post / Hidden Form Field
QueryString
Session
New State Containers in ASP.NET
Cache
Context
ViewState
Web.config and Machine.config Files
Conclusion
It's in the nature of HTTP-protocol that it is stateless.
I'm pretty sure your title should be "global variable does not have the data I want." The dictionary will be constructed each time the page is loaded (postback or otherwise), but because of this line:
if(!isPostBack) {
}
it won't have the data you want on a button click.
In order to notify the page of the click, a post back is performed, so saying !isPostBack (which I'm assuming is set somewhere via Page.IsPostBack) is also saying "if I haven't clicked the button", which is of course not what you want.
In order to get the functionality you want, you should either move the population of the dictionary out of that if block, or else have an else condition that also populates it with data you want.
Another alternative to using the class variable is to store the data in another location. Options include ViewState, Session, Application (if it really is application-wide data), the Cache, and some others as well. It's not clear exactly what the dictionary is doing, so it's hard to say which location would be most appropriate.
One way to get your dictionary to live between requests is to declare it static, or in viewstate as was suggested earlier.
How are you accessing the items in propertyCompany in the button click event? If you are doing that incorrectly, that is more likely the issue.
try this
Dictionary<string, string> propertyCompany;//gloabal variable
protected void Page_Load(object sender, EventArgs e)
{
propertyCompany = new Dictionary<string, string>();
if(!isPostBack){
propertyCompany .add("a","1");
propertyCompany .add("b","2");
propertyCompany .add("c","3");
}
}
protected void btnGetProperty_Click(object sender, EventArgs e)
{
//propertyCompany is null
}
I have an aspx page with a gridview. In my page load event, I load a datatable with all the data like so:
HistoricalPricing historicalPricing = new HistoricalPricing();
DataTable dtHistoricalPricing = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
dtHistoricalPricing = historicalPricing.GetAuctionData();
}
}
The above loades the data into the datatable fine. I also have a listbox which contains a list of auctions. When I click on an auction, I use the RowFilter on a DataView to display a Gridview with the data that was selected, but the DataTable seems to loose its value and I can't figure out why. Here is the code below:
protected void lstAuctions_SelectedIndexChanged(object sender, EventArgs e)
{
DataView dvPricing = new DataView(dtHistoricalPricing); // Loses Value
dvPricing.RowFilter = "Auction = 1"; //Hard-Coded for Test
gvPricing.DataSource = dvPricing.ToTable();
gvPricing.DataBind();
}
Every time you do a postback you're dealing with a new instance of your page class. That means a new datatable object as well.
If you really want to persist it between postbacks (and make sure you consider the memory implications for that when you may have 1000 people hitting this web server at the same time) then you can put the datatable in the Session, ViewState, or other location that persists state.
I think I figured it out, is it because when I click on the ListBox, it does a postback and I am only loading the data on the first load of the Page? If this is correct, I think I answered my own question.
I put the datatable in Session after loading it on the first Page Load and this seemed to solve my problem. Not sure if this is the best way though.
Sort of answered your own question. You are creating a new instance of the object every page load, so when the listbox posts a postback, your code is dealing with a different object.
You would be better to declare the object globally, and then instantiate it in the !Postback code eg:
DataTable dtHistoricalPricing = null;
...
if (!Page.IsPostBack)
{
if (dtHistoricalPosting == null)
{
//shouldn't need to do a new dtHistoricalPricing as the method below is returning a new instance?
dtHistoricalPricing = historicalPricing.GetAuctionData();
}
}
It is difficult to persist values between requests in ASP.NET. The most reliable way would be to put it in ViewState, but that will send the whole thing to the client and back, so you shouldn't put much data there. The session is an alternative, but it can become a problem when a user opens several windows with your page within the same session. Then there is also application state and cache, but those are shared among ALL requests (regardless if user). Plus, if you have a web farm, the values in there are local for every server. Even more, IIS can spawn several ASP.NET processes on the same machine too, and they will each have their own Application State. The same can be said about static variables.