Приостановить привязку данных элементов управления - PullRequest
14 голосов
/ 10 февраля 2011

У меня есть ряд элементов управления, привязанных к значениям, которые меняются каждую секунду или около того.Время от времени мне нужно «приостанавливать» элементы управления, чтобы они не обновляли свои привязки данных (в любом направлении).Затем мне необходимо «отменить приостановку» элементов управления, чтобы они могли обновлять источник данных своими значениями и получать будущие обновления из источника в обычном режиме.Как мне это сделать?

Пример привязки:

<TextBox Text="{Binding UpdateSourceTrigger=LostFocus, Mode=TwoWay, Path=myData}">

Ответы [ 6 ]

12 голосов
/ 11 февраля 2011

Вам не обязательно приостанавливать привязку. Другой и, возможно, более простой способ сделать это - приостановить уведомление об изменении в модели представления. Например:

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();
      }
   }
}

Это (если оно отлажено и протестировано, чего я не делал) прекратит вызывать события PropertyChanged, когда Suspended установлен на true, а когда Suspended установлен на false, снова будет поднять событие для каждого свойства, которое изменилось, пока оно было приостановлено.

Это не остановит изменения связанных элементов управления от обновления модели представления. Я утверждаю, что если вы позволяете пользователю редактировать свойства на экране одновременно с изменением их в фоновом режиме, есть нечто, на что вам нужно присмотреться, и оно не является обязательным.

3 голосов
/ 11 февраля 2011

Чтобы иметь дело с источником, установите UpdateSourceTrigger равным Explicit.

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

Затем в коде ссылки укажите сервис, который может иметь дело с фактическим обновлением, как определено вашими условиями.

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

Это позволит вам указать, в какой момент данные возвращаются к источнику от цели.

Цель может быть решена путем вызова той же службы, на которую имеется ссылка.знание о том, когда вызывать событие INotifyPropertyChanged.PropertyChanged в вашей 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"));
                }
            }
        }
    }
2 голосов
/ 11 февраля 2011

Прежде всего вам нужно создать явное связывание:

Binding binding = new Binding("Content");
binding.Source = source;
binding.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
binding.Mode = BindingMode.TwoWay;
txtContent.SetBinding(TextBox.TextProperty, binding);

Затем, когда вам нужно приостановить двухстороннее связывание, вам нужно уничтожить старое связывание и создать новое одностороннее связывание с явным триггером (в этом случае ваш источник связывания не будетобновляться при изменении какого-либо свойства):

BindingOperations.ClearBinding(txtContent, TextBlock.TextProperty);
Binding binding = new Binding("Content");
binding.Source = source;
binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
binding.Mode = BindingMode.OneWay;
txtContent.SetBinding(TextBox.TextProperty, binding);

Когда вам нужно возобновить привязку twoway, вы можете явно указать источник обновлений (если вам это нужно), чем уничтожить привязку oneway и создать привязку twoway.

BindingExpression be = txtContent.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
BindingOperations.ClearBinding(txtContent, TextBlock.TextProperty);

Binding binding = new Binding("Content");
binding.Source = source;
binding.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
binding.Mode = BindingMode.TwoWay;
txtContent.SetBinding(TextBox.TextProperty, binding);
0 голосов
/ 11 декабря 2017

Мое решение закончилось следующим образом, чтобы предотвратить обновление текста, пока пользователь пытается его изменить.

XAML:

<TextBox Grid.Row="0" Grid.Column="1" TextAlignment="Right" VerticalAlignment="Center" Text="{Binding Path=MinimumValueInDisplayUnit, StringFormat=0.########}" MinWidth="100" Margin="4" GotFocus="TextBox_OnGotFocus" LostFocus="TextBox_OnLostFocus"/>
<TextBox Grid.Row="0" Grid.Column="2" TextAlignment="Right" VerticalAlignment="Center" Text="{Binding Path=MaximumValueInDisplayUnit, StringFormat=0.########}" MinWidth="100" Margin="4" GotFocus="TextBox_OnGotFocus" LostFocus="TextBox_OnLostFocus"/>

Код позади:

    private void TextBox_OnGotFocus([CanBeNull] object sender, [CanBeNull] RoutedEventArgs e)
    {
        TextBox tb = sender as TextBox;
        if (tb == null) return;
        BindingExpression expression = tb.GetBindingExpression(TextBox.TextProperty);
        if (expression == null) return;
        // disable updates from source
        BindingOperations.ClearBinding(tb, TextBlock.TextProperty);
        tb.SetBinding(TextBox.TextProperty, new Binding(expression.ParentBinding.Path.Path) { Mode = BindingMode.OneWayToSource, UpdateSourceTrigger = UpdateSourceTrigger.Explicit , FallbackValue = tb.Text});
    }

    private void TextBox_OnLostFocus([CanBeNull] object sender, [CanBeNull] RoutedEventArgs e)
    {
        TextBox tb = sender as TextBox;
        if (tb == null) return;
        BindingExpression expression = tb.GetBindingExpression(TextBox.TextProperty);
        if (expression == null) return;
        // send current value to source
        expression.UpdateSource();
        // enable updates from source
        BindingOperations.ClearBinding(tb, TextBlock.TextProperty);
        tb.SetBinding(TextBox.TextProperty, new Binding(expression.ParentBinding.Path.Path) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.LostFocus });
    }

Обратите внимание, что я назначаю текущий текст в качестве запасного значения привязки OneWayToSource, чтобы иметь начальное значение (в противном случае текстовое поле было бы пустым после фокусировки)

0 голосов
/ 11 сентября 2012

Если элемент управления, который вы хотите приостановить, имеет собственный DataContext (ViewModel), просто сохраните его и обнулите DataContext.

Если у элемента управления есть унаследованный DataContext, установка значения DataContext этого элемента управления на ноль блокирует наследование. Затем, чтобы возобновить связывание обновлений, вы используете метод ClearValue, чтобы очистить DataContext DependencyProperty, чтобы наследование возобновилось.

Вы можете проявить фантазию и использовать VisualBrush, чтобы сделать снимок экрана элемента управления, который вы приостанавливаете, перед очисткой его DataContext, чтобы пользователь не увидел, что элемент управления пуст.

0 голосов
/ 10 февраля 2011

Если вы сохраняете ссылку на представление в классе контроллера, вы можете запустить событие из модели представления, если вы хотите приостановить сбор данных, когда контроллер очищает DataContext представления.и когда вы будете готовы начать отправку полученных данных снова, сбросьте DataContext Views в модель представления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...