Window Form textbox won't refresh when datasource modified

Window Form textbox won't refresh when datasource modified

Old forum URL: forums.lhotka.net/forums/t/821.aspx


Brian Tian posted on Friday, August 04, 2006

Hi, All,

I have a window form with several textboxes and these textboxes  bind to a Winodw.Form.BindingSource, for example, bsActivity.  Also, the bsActivity.DataSource is set to a root object m_activity. I have two read-only textboxes called modified user and modified date. When the object is updated, it is saved into the databse and  these two fields is updated too. After it calls Save( ) and sets the BindingSource.DataSource to new modified object, (here, the m_activity has the new modified user and date info) but why the UI won't refresh with new info for modified user and date? I even try bs.Activity.ResetBindings(false), but it won't work either. When I close the form and re-open it, I can see the modified user and date. What should I do if I want to refresh the UI when dataSource is modified?

Thanks for your help and have a good weekend.

here is the code snippet.

this.bsActivity.RaiseListChangedEvents = false;
this.bsActivity.EndEdit();

activity temp = this.m_activity.Clone();
temp.ApplyEdit();
try
{
         m_activity = temp.Save();
         
m_activity.BeginEdit();
         
this.bsActivity.DataSource = m_activity;
         //this.bsActivity.ResetBindings(false);

}
catch (.... )
{
   .......
}

ajj3085 replied on Friday, August 04, 2006

I would suggest this:

Activity temp = m_activity.Clone();
temp.ApplyEdit();

try {
   m_activity = temp.Save();
   bsActivity.DataSource = null;
   bsActivity.DataSource = m_activity;
}
catch {
// handle
}

To answer your question, you turn off RaiseListChangedEvents, and never turn it back on.  I think that may be causing the problem you describe.  Don't need to worry about turning of the events, or manually resetting bindings, but you need to null the datasource for the BS to pick up on the changes, since the reference may not actually be changing if you're not using remoting.

Andy

Brian Tian replied on Friday, August 04, 2006

Andy,

Thank you, I do turn on RaiseListChangedEvents, it is on finally { } parte of Try /Catch but it is not shown at the code snippet. Sorry about that.

I use your way, bsActivity.DataSource = null;  bsActivity.DataSource = m_activity; but the two textboxes still don't refresh after saving the object.

Best regards,


 

xal replied on Friday, August 04, 2006

Brian, could you paste your update / insert method?

Are you sure you're retrieving the new values back from the command once you persist the object to the db?

Andrés

Brian Tian replied on Friday, August 04, 2006

Hi, Andres,

Here is the update method. After saved the object, I use the output parameter to get the modified date value and modified user is  from Csla.ApplicationContext.User.Identity.Name.

I' m sure that I get the modified date and user in new BS, but just can not refersh window UI.

Thanks and have a good weekend.

[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
      using (SqlConnection cn = new SqlConnection(Database.ShowSupportConnection))
      using (SqlCommand cm = cn.CreateCommand())
      {
            cn.Open();
            if (base.IsDirty)
            {
               cm.CommandType = CommandType.StoredProcedure;
               cm.CommandText = "usp_UpdateActivity";
               cm.Parameters.AddWithValue("@id", this._id);
               cm.Parameters.AddWithValue("@segment_id", this._segmentId);
               cm.Parameters.AddWithValue("@code", this._code);
               cm.Parameters.AddWithValue("@description", this._description);
               cm.Parameters.AddWithValue("@notes", this._notes);
               cm.Parameters.AddWithValue("@user_name", Csla.ApplicationContext.User.Identity.Name)
               cm.Parameters.AddWithValue("@change_stamp", this._changeStamp);

               SqlParameter par = new SqlParameter("@newChange_Stamp", SqlDbType.Timestamp);
               par.Direction = ParameterDirection.Output;      
               
cm.Parameters.Add(par);

               
SqlParameter par1 = new SqlParameter("@Newmodified_date", SqlDbType.DateTime);
               par1.Direction = ParameterDirection.Output;
               
cm.Parameters.Add(par1);

               cm.ExecuteNonQuery();

               _changeStamp = (byte[])cm.Parameters["@Newchange_stamp"].Value;
               
this._modifiedDate.Text = cm.Parameters["@Newmodified_date"].Value.ToString();
               
this._modifiedUser = Csla.ApplicationContext.User.Identity.Name;   
      
}//if(base.IsDirty)

      
UpdateChildren(cn);
   }
//using

}

ajj3085 replied on Monday, August 07, 2006

Hmm... are your text boxes readonly?  i've noticed I'm experiencing similar behavior. Maybe the databinding doesn't re-read values for readonly text boxes even if the source changes? 

Andy

tsmo replied on Monday, August 07, 2006

The problem is a sneaky one.  There are two issues:

1) You aren't listening for changes on temp, and that is the object being saved (and therefore the object that is being changed by Update()).

2) Change notification for m_activity has been disabled by setting RaiseListChangedEvents equal to false.

The simplest solution is probably moving your ResetBindings call until the finally block, after you have turned RaiseListChangedEvents back on.  Alternately (and there may be repercussions with this technique I'm unaware of), you can leave RaiseListChangedEvents on, and instead of resetting the binding source by:

this.bsActivity.DataSource = null;
this.bsActivity.DataSource = m_activity;

resetting the binding source with:

this.bsActivity.DataSource.Clear();
this.bsActivity.DataSource.Add(m_activity);

tsmo

ajj3085 replied on Monday, August 07, 2006

Tsmo,

The changes I'm listening to are from the BindingSource control, not the instance object.  Also, calling ResetBindings( false ) doesn't work for me (nothing happens).

Also, resetting the binding doesn't work either:

bsContact.DataSource = typeof( Contact ); // using null causes binding errors
bsContact.DataSource = EditedContact;

tsmo replied on Monday, August 07, 2006

Are you sure that RaiseListChangedEvents has been turned back on prior to your call to ResetBindings?

tsmo

ajj3085 replied on Monday, August 07, 2006

I don't turn them off (the OP was doing that).

I sorta found the problem; no PropertyHasChanged method being called (duh). 

What's odd though is that the controls bound to a SmartDate property aren't refreshing, although the string properties are.  Need to look into that more, I'll post back when I figure out whats wrong.

Andy

Brian Criswell replied on Monday, August 07, 2006

ajj3085:
I don't turn them off (the OP was doing that).

I sorta found the problem; no PropertyHasChanged method being called (duh). 

What's odd though is that the controls bound to a SmartDate property aren't refreshing, although the string properties are.  Need to look into that more, I'll post back when I figure out whats wrong.

Andy

Doesn't this go back to the old "don't expose the property as a SmartDate, expose it as a string" thing?  SmartDate does not raise an event (as far as I know) when one of its properties changes, so your object will not know that it has changed and will not raise a PropertyChanged event.

ajj3085 replied on Monday, August 07, 2006

My object knows when the date is changed because I set it in code, and the (private) setter calls the PropertyHasChanged method.

Incidently, because Smartdate is a struct, you can't do something like this:

myInstance.SmartDateField.Text = "52"; // throws an exception.


At any rate, adding the appropriate methods and setting the databinding properly DOES work for the dates now as well... so to the OP, I would recommend that in the designer set the databinding for the Text property of the text box, and making sure that your property setters call PropertyHasChanged.

That's what solved it for me.

Brian Tian replied on Tuesday, August 08, 2006

Thanks for everyone's help.

The way Tmso said works for me.( RaiseListChangedEvents has been turned back on prior to your call to ResetBindings).

Thank you all.

here is snippet code:

this.bsActivity.RaiseListChangedEvents = false;
this.bsActivity.EndEdit();

activity temp = this.m_activity.Clone();
temp.ApplyEdit();
try
{
         m_activity = temp.Save();

}
catch (.... )
{
   .......
}
finally
{
         bsCategory.RaiseListChangedEvents =
true;
          m_activity.BeginEdit();
         
this.bsActivity.DataSource = m_activity;
}

dcb replied on Tuesday, August 08, 2006

What I have done in the past is to create a DataBind method and a DataUnBind method.  After a save I call DataUnBind and then DataBind.

David

 

Copyright (c) Marimer LLC