Связанная кнопка не активируется после завершения фонового рабочего процесса - PullRequest
0 голосов
/ 01 ноября 2011

У меня есть фоновый рабочий процесс, который начинает подготовку нового клиента для нашей системы. Вот как выглядит метод DoWork:

ProvisioningManager manager = new ProvisioningManager(false)
{
};

System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
{
    this.MaxSteps = manager.MaxProgress;
}));

manager.StatusUpdated += new ProvisioningManager.StatusUpdatedHandler(manager_StatusUpdated);
manager.TaskCompleted += new ProvisioningManager.TaskCompleteHandler(manager_TaskCompleted);

manager.ProvisionClient();
while (!manager.Completed)
{
    System.Threading.Thread.Sleep(100 * 60);
}

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

Теперь у меня есть событие обновления статуса и завершенное событие для менеджера инициализации. Когда возникает событие TaskCompleted, я хочу иметь возможность установить свойство для моего экранного объекта, чтобы была включена кнопка завершения в мастере:

void manager_TaskCompleted(object sender, ProvisioningManager.Task taskType)
{
    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
    {
        this.ProvisioningComplete = true;
    }));
}

XAML для кнопки выглядит следующим образом:

<wizard:WizardPage Header="Provisioning Client..."
                               ShowBack="False" 
                               AllowBack="False" 
                               AllowFinish="{Binding Source={StaticResource ResourceKey=dataObject}, Path=ProvisioningComplete}" 
                               Loaded="Provisioning_Loaded">
</wizard:WizardPage>

Это не работает. Несмотря на то, что я проверяю поток диспетчера, чтобы установить свойство экранного объекта, он фактически не меняет кнопку на включенную, пока я не нажму на окно. Это ошибка в AvalonWizard или я не в том потоке, чтобы установить INotifyPropertyChanged? Есть ли способ взломать это; в основном я могу программно сфокусировать окно без щелчка мышью?

Мне надоело размещать цикл while в методе DoWork, чтобы я мог использовать завершенный метод BackgroundWorker:

void provisioningWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
    {
        this.ProvisioningComplete = true;
    }));
}

Это тоже не работает. Что дает?!

Обновление Вот запрашиваемая реализация статического ресурса для экранного объекта:

<Window.Resources>
    <ObjectDataProvider x:Key="dataObject" ObjectType="{x:Type winDO:NewClientWizardDO}" />
</Window.Resources>

Обновление II Вот собственность и изменение собственности firer:

public bool ProvisioningComplete
{
    get { return this._ProvisioningComplete; }
    set
    {
        this._ProvisioningComplete = value;
        this.NotifyPropertyChanged("ProvisioningComplete");
    }
}

protected void NotifyPropertyChanged(params string[] propertyNames)
{
    if (this.PropertyChanged != null)
    {
        foreach (string propertyName in propertyNames)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Ответы [ 2 ]

0 голосов
/ 20 декабря 2011

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

Разумный член моей команды предложил щелкнуть мышью по окну. Его идея заключалась в том, что, поскольку для активации кнопки достаточно простого щелчка мышью по экрану, подделка должна иметь тот же эффект. Я думал (и думаю), что этот взлом был нелепым. Я попробовал это, просто чтобы посмотреть, смогу ли я назвать это «решением».

Ну, это сработало. У нас была такая же проблема в другом мастере (не AvalonWizard, а доморощенный). Я думаю, что должна быть некоторая основная проблема с тем, как окно перерисовывается после того, как фоновый поток обновляет объекты, связанные с пользовательским интерфейсом.

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

//import user32.dll and setup the use of the mouse_event method
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

/// <summary>
/// Watches for properties to change on the data object, mainly the ProvisioningComplete method
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void DataObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "ProvisioningComplete":
            //if the provisioning is completed then we need to make the finish button selectable.
            if (this.DataObject.ProvisioningComplete)
            {
                System.Windows.Application.Current.Dispatcher.Invoke((Action)(() =>
                {
                    //give the window focus
                    this.Focus();
                    //update the layout
                    WizardPageProvisioningClient.UpdateLayout();
                    //fake mouse click 50 pixels into the window
                    mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, (uint)(this.Left + 50), (uint)(this.Top + 50), 0, 0);
                }));
            }
            break;
    }
}

Я проверял это, когда окно не является активным окном и когда пользователь покидает окно как выбранное. Метод фокусировки, кажется, решает эту проблему, когда окно не активно. Наша команда QA еще не провела полный тест на пользовательский интерфейс, поэтому я не могу сказать, есть ли ситуации, когда он не работает, но, похоже, это лучшее решение, которое я придумал на сегодняшний день.

Я открыт для любых других предложений, если у кого-то есть лучшее представление о том, что может быть причиной того, что кнопка не обновляется.

0 голосов
/ 02 ноября 2011

извините, если я чего-то не понимаю, но помечено ли свойство ProvisioningComplete как "volatile"? Если нет, то это может быть проблемой.

...