Привязка, где изменения значений хранятся непосредственно в БД - PullRequest
0 голосов
/ 24 июня 2010

В настоящее время я борюсь с одной из привязок, которые пытаюсь добавить в свой проект WPF. В приложении у меня есть модель со свойством bool, которое нельзя использовать для привязки данных. За этим свойством находится объект удаленного взаимодействия .NET, который выполняет некоторую проверку и записывает новое значение в БД.

Требуется, чтобы свойство отображалось как флажок, и, когда пользователь изменяет значение, новое значение должно быть немедленно предоставлено объекту удаленного взаимодействия .NET.

Мой подход пока: Я создал в своей модели представления с DependencyProperty, который связан с моим флажком. В обработчике DP, измененном свойством, я записываю значение в свойство удаленного объекта.

Проблемы у меня с этим подходом: если проверка в объекте удаленного взаимодействия .net вызывает исключение, это исключение проглатывается. Кроме того, состояние флажка и то, что находится в БД, не синхронизировано. Я попытался сбросить значение DP в случае исключения, но флажок не отражает это. Еще хуже то, что этот элемент управления WPF интегрирован в существующее приложение WinForms. Поэтому я хотел бы иметь такое же поведение для этих исключений, как я реализовал в своем обработчике Application.ThreadException.

есть идеи как подойти? Проблема в том, что я до сих пор слышал только решения для .NET 4.0, но я работаю с 3.5SP1.

ТИА Martin

Короткий демонстрационный код:

class TestVM : DependencyObject
{
private Model _m;
public TestVM()
{
  _m = new Model();
}

public bool Value
{
  get { return (bool)GetValue(ValueProperty); }
  set { SetValue(ValueProperty, value); }
}

// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register("Value", 
                typeof(bool), 
                typeof(TestVM), 
                new FrameworkPropertyMetadata(
                   false,
                   FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                   ((sender, e) => ((TestVM)sender).Apply(e))));

private bool _suppress = false;
private void Apply(DependencyPropertyChangedEventArgs e)
{
  if (_suppress) return;
  try
  {
    _m.Value = this.Value;
  }
  catch
  {
    _suppress = true;
    this.Value = _m.Value;
    this.OnPropertyChanged(e);
  }
  finally
  {
    _suppress = false;
  }
}

}

Ответы [ 2 ]

0 голосов
/ 29 сентября 2010

Я нашел решение для моей проблемы. Сейчас я создаю свой собственный класс связывания, который выполняет эту работу.

public class ExceptionBinding : Binding
{
    public ExceptionBinding(string name)
        : base(name)
    {
        Construct();
    }

    public ExceptionBinding()
        : base()
    {
        Construct();
    }

    private void Construct()
    {
        this.ValidatesOnExceptions = true;
        this.UpdateSourceExceptionFilter = new UpdateSourceExceptionFilterCallback(OnException);
    }

    private object OnException(object bindExpression, Exception exception)
    {
        // ... custom error display ...
        var exp = (BindingExpressionBase)bindExpression;
        exp.UpdateTarget();
        return null; // null needed to avoid display of the default error template
    }
}
0 голосов
/ 24 июня 2010

Вам не нужно использовать DependencyObject в качестве вашей ViewModel.Вам просто нужно реализовать INotifyPropertyChanged, чтобы получить поддержку привязки данных:

class TestVM
    : INotifyPropertyChanged
{
    private Model _m;
    public TestVM()
    {
        _m = new Model();
    }

    public bool Value
    {
        get { return _m.Value; }
        set 
        {
            _m.Value = this.Value;
            OnPropertyChanged("Value");
        }
    }

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

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


Обновление: Похоже, ваша проблема в том, что Binding не будет реагировать на события PropertyChanged в вызове, чтобы установить источник.Один из способов обойти это - использовать асинхронную привязку, установив IsAsync=True в XAML для вашей привязки.WPF обработает событие PropertyChanged после завершения обновления исходного значения и не будет думать, что это повторный входящий вызов.

Вы также можете обойти это, используя конвертер и отключив обновления на PropertyChanged, выполнив UpdateSourceTrigger=LostFocus, но я не думаю, что вы захотите такое поведение.

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