Общий сервис Prism6 и свойство зависимостей - PullRequest
0 голосов
/ 05 марта 2019

Я использую контейнер Prism6 + Unity для разработки настольных приложений. Это давно прочитано, извините. Поэтому я спрашиваю в верхней части: функция Prism SetProperty () не является событием изменения свойства, если входное значение равно Unity singleton. И я понимаю почему: потому что входное значение и сохраненное значение имеют одинаковую ссылку на одноэлементный экземпляр. RaisePropertyChanged () не помогает в этой ситуации. Долгое чтение статинга ...

Итак, у меня есть свойство зависимостей в моем компоненте UserControl:

    public static readonly DependencyProperty WorksheetDataProperty =
        DependencyProperty.Register("WorksheetData", typeof(WorksheetDataModel), typeof(SheetUserControl),
        new PropertyMetadata(new WorksheetDataModel(), WorksheetDataPropertyChanged));
    public WorksheetDataModel WorksheetData {
        get { return (WorksheetDataModel)GetValue(WorksheetDataProperty); }
        set { SetValue(WorksheetDataProperty, value); }
    }
    private void WorksheetDataPropertyChanged(WorksheetDataModel worksheetData) {
        if (worksheetData == null)
            return;
        SheetGrid.Model.ActiveGridView.BeginInit();
        this.ClearWorksheetModel();
        this.ResizeWorksheetModel();
        SheetGrid.Model.ActiveGridView.EndInit();
    }
    private static void WorksheetDataPropertyChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e) {
        ((SheetUserControl)d).WorksheetDataPropertyChanged((WorksheetDataModel)e.NewValue);
    }

Для меня важно вызывать действия из функции WorksheetDataPropertyChanged (). И схема без общего сервиса (singleton) работает хорошо: эта функция называется.

Но теперь я хочу поделиться данными между несколькими модулями. Как я это вижу: у меня есть какой-то «родительский» модуль, который загружает \ сохраняет данные из хранилища и делится этими данными с несколькими другими модулями, которые могут изменять общие данные, но не могут их сохранить. И EventAggregator мне не удобен: я не хочу создавать копии данных, а затем собирать их снова после внесения изменений. Поэтому я регистрирую свой «общий сервис» как singleton:

_container.RegisterInstance(new WorksheetDataModel());

Теперь я могу загрузить данные из базы данных в «родительской» модели представления в одноэлементный объект, созданный на предыдущем шаге:

    var data = _container.Resolve<WorksheetDataModel>();
    data.Header = args.Header;
    data.User = args.User;
    data.RowHeader = new WorksheetRowHeader(_model.ReadRowHeader(data.Header.WshCode));
    data.ColHeader = new WorksheetColHeader(_model.ReadColHeader(data.Header.WshCode));
    data.Cells = _model.ReadCells(data.Header.WshCode);

Далее я уведомляю дочерние модели представления о новых данных в синглтоне:

    data.OnDataChanged?.Invoke();

А теперь самый важный код из дочерней viewmodel. В обработчике делегата я «применяю» новое значение:

WorksheetData = _container.Resolve<WorksheetDataModel>();

Данные рабочего листа:

    private WorksheetDataModel _worksheetData;
    public WorksheetDataModel WorksheetData {
        get { return _worksheetData; }
        set { SetProperty(ref _worksheetData, value); }
    }

И проблема в этой строке:

set { SetProperty(ref _worksheetData, value); }

Он работает только один раз при первом вызове, потому что _worksheetData имеет значение null. Но тогда ссылка на _worksheetData (указатель), установленный на singleton и во всех следующих значениях вызова и _worksheetData, идентична для SetProperty () и, как результат, просто завершается.

Я попробовал следующий код:

set { 
    SetProperty(ref _worksheetData, value); 
    RaisePropertyChanged("WorksheetData")
}

Но никакого эффекта. Обратный вызов WorksheetDataPropertyChanged () в компоненте UserControl не вызывается.

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

1 Ответ

0 голосов
/ 06 марта 2019

WorksheetData не изменяется, содержимое экземпляра WorksheetDataModel изменяется.

Итак, чтобы обновить ваши привязки,

  • либо WorksheetDataModel реализует INotifyPropertyChanged и / или использует INotifyCollectionChanged реализующие коллекции
  • или вы позволяете модели представления прослушивать WorksheetDataModel.OnDataChanged и поднимаете свой собственный PropertyChanged, чтобы обновить все привязки до WorksheetData.

Пример:

private WorksheetDataModel _worksheetData;
public WorksheetDataModel WorksheetData
{
    get { return _worksheetData; }
    set
    {
        if (_worksheetData != null)
            _worksheetData.OnDataChanged -= DataChangedHandler;
        SetProperty(ref _worksheetData, value);
        if (_worksheetData != null)
            _worksheetData.OnDataChanged += DataChangedHandler;
    }
}

private void DataChangedHandler( object sender, DataChangedEventArgs args )
{
    RaisePropertyChanged( nameof( WorksheetData ) );
}
...