Небольшой фон
Я создаю приложение, использующее архитектуру плагинов для доступа к конкретным устройствам.Эти устройства имеют поля, которые я назвал Атрибуты, которые могут быть прочитаны, записаны или оба.Это делается с помощью внешнего интерфейса WPF, работающего в своем собственном потоке, и MVVM-подобной структуры во внутреннем интерфейсе, которая оборачивает определенный плагин для общего представления его атрибутов.
Некоторые сведения оструктура потоков
У меня есть два объекта "хоста", один инициирует структуры подключаемых модулей, в конечном итоге предоставляет два представления: представление доступных подключаемых модулей и (если был выбран подключаемый модуль) представлениевсех атрибутов, известных одному плагину.Другой в конечном итоге запускает STA-поток и запускает главное окно в приложении WPF.Второй хост использует BackgroundWorkers для выбора, инициализации, обновления и отправки задач.События / делегаты DoWork (я полагаю, что они называются делегатами) определены в классе ViewController, который находится в структуре MVVM и предоставляет функциональный интерфейс для обновления и т. Д. И реализует интерфейс INotifyPropertyChanged.
Некоторыеподробнее
При создании главного окна его контекст устанавливается на объект контроллера представления.Затем графический интерфейс привязывает два списка к обоим представлениям.
Проблема
Когда я вызываю метод selectPlugin из потока пользовательского интерфейса, он останавливается до завершения операции подключенияи каждый отдельный атрибут загружается в список, содержащийся в ViewModel.Однако это работает, и после этого привязка источника элементов ListBox обновляется и отображаются все атрибуты.
Однако я не хочу, чтобы пользовательский интерфейс зависал при каждой операции, поэтому я реализовал фоновые рабочие.Все работает нормально, объекты обновляются, а источник привязки заменяется новым экземпляром View.Но сама привязка не обновляется.
Я пытался выделить различные решения, используя событие Dispatcher.Invoke или DoWorkComplete в потоке пользовательского интерфейса.Я обнаружил, что само событие PropertyChanged остается нулевым, используя следующий установщик свойств:
public IAttributesViewModel AttributesView
{
get
{
StaticLogger.WriteDebugLog(log,
String.Format("Executing {0}",
System.Reflection.MethodBase.GetCurrentMethod()));
return _currentAttributes;
}
set
{
_currentAttributes = value;
OnPropertyChanged("AttributesView");
}
}
Реализация INotifyPropertyChanged выглядит следующим образом:
#region INotifyPropertyChange implementation
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Called when [property changed].
/// </summary>
/// <param name="name">The name.</param>
protected void OnPropertyChanged(string name)
{
StaticLogger.WriteDebugLog(log, String.Format("Executing {0}", System.Reflection.MethodBase.GetCurrentMethod()));
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
Событие PropertyChanged, как объявлено выше, всегда равно нулю,Это может или должно иметь какое-то отношение к фактическому связыванию в XAML, однако я установил de datacontext главного окна в потоке пользовательского интерфейса следующим образом:
private static void Host(object viewControler)
{
var controler = viewControler as IViewController;
_instance._main = new MainWindow(controler) { DataContext = controler };
var gui = new App();
if (_instance._main == null) throw new ArgumentNullException("viewControler");
gui.Run(_instance._main);
}
Я использую экземпляр Singleton с хоста пользовательского интерфейсаобъект, в случае, если это имеет значение.
В XAML я использую пользовательское свойство зависимости для UserControll, содержащее AttributesListbox и некоторый код стиля.Фактический ListBox привязывается к этому свойству для своего собственного свойства ItemSource.Не думайте, что это должно отличаться от непосредственного использования списка, но только в том случае, если это вызывает проблему с событием PropertyChanged, равным нулю, и реализуется следующим образом:
C # /// /// Логика взаимодействия для AttributesListBox.xaml /// открытый частичный класс AttributesListBox: UserControl {частная статическая только для чтения UIPropertyMetadata _sourceMetadata = new UIPropertyMetadata (String.Empty, SourceChangedCallback) 10 1045 * 10 10 * 10 * 10 * 10 * 10 * 10* XAML
<ListBox Name="List" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding Source}" BorderBrush="{x:Null}" />
Первый вопрос (ы)
Что плохого в том, как я использую объект ViewController в сочетании с пользовательским интерфейсом?И, таким образом, почему событие PropertyChanged всегда равно null?Это должно означать, что я где-то испортил процесс привязки, не так ли?
Второй вопрос (ы)
Как получить событие OnPropertyChanged для уведомления пользовательского интерфейсанить, специфичность привязки в UserControll (AttributesListbox)?
По какому маршруту проходит мероприятие?
например:Я использую делегат DoWork, и этот метод изменяет свойство непосредственно из экземпляра, которого нет в потоке пользовательского интерфейса. Приводит ли это к тому, что событие никогда не достигает потока пользовательского интерфейса, потому что оно вызывается в другом рабочем потоке?
Я не могу разобраться с событием пузыри / туннелирования, это событие ограничено потоком, который создал экземпляр, или потоком, который вызвал определенный метод (с использованием диспетчера или чего-то еще)?
Гипотеза
Я подозреваю, что в моем случае есть две проблемы:
1. Обработчик PropertyChanged остается нулевым, поскольку объект либо не связан, либо потому, что он не создан в правильном потоке.
2. Событие, если оно действительно запущено, никогда не достигает нужного потока, поскольку оно застревает либо в потоке BackgroundWorker, либо во внутреннем потоке «хоста».
Это первый вопрос, который я задал здесь, поэтому, если вы пропустили несколько кусочков головоломки, пожалуйста, сообщите мне.
Спасибо, что нашли время прочитать мою маленькую проблемную ситуацию, надеюсь, мы сможем найти решение.