Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suspend Databinding of Controls

I have a series of controls that are databound to values that change every second or so. From time to time, I need to "pause" the controls, so that they do not update their databindings (in either direction). I then later need to "unpause" the controls, so that they can update the datasource with their values, and receive future updates from the source as normal. How do I accomplish this?

Sample Binding:

<TextBox Text="{Binding UpdateSourceTrigger=LostFocus, Mode=TwoWay, Path=myData}">
like image 692
GWLlosa Avatar asked Feb 10 '11 20:02

GWLlosa


People also ask

What is databinding in VB net?

Description. Simple data binding. The ability of a control to bind to a single data element, such as a value in a column in a dataset table. Simple data binding is the type of binding typical for controls such as a TextBox control or Label control, which are controls that typically only display a single value.

What is control binding?

Controls -> Child Control Data Binding is binding controls to data from databases. With data binding we can bind a control to a particular column in a table from the database or we can bind the whole table to the data grid.

What is data binding in database?

Data binding is the process that couples two data sources together and synchronizes them. With data binding, a change to an element in a data set automatically updates in the bound data set.


2 Answers

You don't necessarily have to suspend binding. Another, and possibly simpler, way to do this is to suspend change notification in the view model. For instance:

private HashSet<string> _ChangedProperties = new HashSet<string>();

private void OnPropertyChanged(string propertyName)
{
   if (_Suspended)
   {
      _ChangedProperties.Add(propertyName);
   }
   else
   {
      PropertyChangedEventHandler h = PropertyChanged;
      if (h != null)
      {
         h(this, new PropertyChangedEventArgs(propertyName));
      }
   }
}

private bool _Suspended;

public bool Suspended
{
   get { return _Suspended; }
   set
   {
      if (_Suspended == value)
      {
         return;
      }
      _Suspended = value;
      if (!_Suspended)
      {
         foreach (string propertyName in _ChangedProperties)
         {
            OnPropertyChanged(propertyName);
         }
         _ChangedProperties.Clear();
      }
   }
}

This will (if it's debugged and tested, which I haven't done) stop raising PropertyChanged events when Suspended is set to true, and when Suspended is set to false again it will raise the event for every property that changed while it was suspended.

This won't stop changes to bound controls from updating the view model. I submit to you that if you're letting the user edit properties on the screen at the same time that you're changing them in the background, there's something you need to take a closer look at, and it's not binding.

like image 199
Robert Rossney Avatar answered Sep 19 '22 07:09

Robert Rossney


To deal with the source set the UpdateSourceTrigger to be Explicit.

<TextBox Name="myTextBox" Text="{Binding UpdateSourceTrigger=Explicit, Mode=TwoWay, Path=myData}">

Then in code behind reference a service which can deal with the actual updating as defined by your conditions.

BindingExpression be = myTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();

This will allow you to specify at which point the data goes back to the source from the target.

The target can be addressed by making a call to the same referenced service which has the knowledge on when to call the INotifyPropertyChanged.PropertyChanged event within your ViewModel.

    class Data : INotifyPropertyChanged
    {
        Manager _manager;

        public Data(Manager manager)
        {
            _manager = manager;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        String _info = "Top Secret";
        public String Information
        {
            get { return _info; }
            set 
            {
                _info = value;

                if (!_manager.Paused)
                {
                    PropertyChangedEventHandler handler = PropertyChanged;
                    if (handler != null)
                        handler(this, new PropertyChangedEventArgs("Information"));
                }
            }
        }
    }
like image 20
Aaron McIver Avatar answered Sep 19 '22 07:09

Aaron McIver