我有一个后台工作程序进程,开始为我们的系统配置新客户端。这是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?有没有办法破解这个;我可以在没有鼠标点击的情况下以编程方式聚焦窗口吗?
我厌倦了在DoWork方法中放置while循环,以便我可以使用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 这是财产和财产变更消防员:
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));
}
}
答案 0 :(得分:0)
抱歉,如果我不明白,但ProvisioningComplete属性是否标记为“volatile”?如果没有那么这可能就是问题所在。
答案 1 :(得分:0)
所以我无法确切地知道为什么我遇到这个问题。我尝试将焦点设置到窗口,按钮等。我尝试了多种让视图知道viewmodel已更新的方法。基本上我在网上找到的每一个建议都不起作用。这几乎就像一个错误。
我团队的一个聪明人建议在窗口上点击鼠标。他的想法是,因为激活按钮所需要的只是在屏幕上点击一个简单的鼠标然后伪造一个应该具有相同的效果。我想(并且认为)这个黑客是荒谬的。我确实尝试过,看看我是否可以将其称为“解决方案”。
嗯,它奏效了。我们在另一个巫师中遇到了同样的问题(不是AvalonWizard,而是本土的)。我认为在后台线程更新绑定到UI的对象后窗口重绘的方式存在一些潜在的问题。
无论如何,我找到解决这个问题的方法是使用以下hack-tastic代码。
//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;
}
}
当窗口不是活动窗口并且用户离开窗口时,我已经测试了这个。当窗口未激活时,焦点方法似乎会解决此问题。我们的质量保证团队没有针对用户界面进行完整的测试,所以我不能说是否有任何不起作用的情况,但它似乎是我迄今为止提出的最佳解决方案。 / p>
如果有人能更好地了解可能导致按钮无法更新的内容,我会接受任何其他建议。