如何强制禁用wpf窗口/控制刷新已禁用的元素

时间:2020-12-13 07:27:50

I was pulling out my hair trying to figure out why the normal Dispatcher.Invoke command did not work for redrawing my window, but now I the issue seems to be related to the content being disabled. I'm using the Dotnet 4.0 full framework.

我将退出我的头发试图找出为什么正常Dispatcher.Invoke命令没有重绘我的窗口中工作,但现在我的问题似乎是相关的内容被禁用。我正在使用Dotnet 4.0完整框架。

If i use

如果我使用

private void DoSomething()
{
  HandleBusyEnableDisable(false);
  DoSomethingThatKeepsItBusy();
  HandleBusyEnableDisable(true);
}

private void HandleBusyEnableDisable(bool enabling)
{
  Cursor = enabling ? Cursors.Arrow : Cursors.Wait; 
  CanvasFunctions.IsEnabled = enabling;
  CanvasRight.IsEnabled = enabling;
  CanvasRight.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, EmptyDelegate);

I see the cursor change but the content does not look disabled. If i add

我看到光标更改但内容看起来没有禁用。如果我添加

CanvasRight.Opacity = enabling ? 1 : .5;

then i think it works, sometimes. Is there something else i can do?
The task that's running is validating user entered data, so its much easier to run on the GUI thread. This shouldn't be that hard.

然后我认为它有效。还有别的我可以做的吗?正在运行的任务是验证用户输入的数据,因此更容易在GUI线程上运行。这不应该那么难。

2 个解决方案

#1


1  

Not all controls visually represent being disabled, you may note that they wont be usable from the client side.

并非所有控件都在视觉上表示被禁用,您可能会注意到它们无法从客户端使用。

To be frank you should probably just implement INotifyChanged and bind the enabled field to the property. This will make sure the controls enable/disable properly as the Binding Framework will do the correct dispatches as IsEnabled I believe is registered with AffectsRender which will invalidate the control's visual state and force a re-draw.

坦率地说,您应该只实现INotifyChanged并将启用字段绑定到属性。这将确保控件正确启用/禁用,因为绑定框架将执行正确的调度,因为IsEnabled我相信已向AffectsRender注册,这将使控件的视觉状态无效并强制重新绘制。

Also you should use a Style to adjust the visual state of the Control:

您还应该使用样式来调整控件的可视状态:

<Style TargetType="Grid">
  <Style.Triggers>
    <DataTrigger Property="IsEnabled" Value="False">
       <Setter Property="Opacity" Value="0.5" />
    </DataTrigger>
  </Style.Triggers>
</Style>

#2


0  

If you're running the long running validation operation on the UI thread, you're locking up the UI and it can't update Visuals until the validation is complete. By that time you've already re-enabled the controls. If the operation is long enough that the user would notice it should be done on a background thread.

如果您正在UI线程上运行长时间运行的验证操作,那么您将锁定UI,并且在验证完成之前无法更新Visual。到那时你已经重新启用了控件。如果操作足够长,用户会注意到它应该在后台线程上完成。

#1


1  

Not all controls visually represent being disabled, you may note that they wont be usable from the client side.

并非所有控件都在视觉上表示被禁用,您可能会注意到它们无法从客户端使用。

To be frank you should probably just implement INotifyChanged and bind the enabled field to the property. This will make sure the controls enable/disable properly as the Binding Framework will do the correct dispatches as IsEnabled I believe is registered with AffectsRender which will invalidate the control's visual state and force a re-draw.

坦率地说,您应该只实现INotifyChanged并将启用字段绑定到属性。这将确保控件正确启用/禁用,因为绑定框架将执行正确的调度,因为IsEnabled我相信已向AffectsRender注册,这将使控件的视觉状态无效并强制重新绘制。

Also you should use a Style to adjust the visual state of the Control:

您还应该使用样式来调整控件的可视状态:

<Style TargetType="Grid">
  <Style.Triggers>
    <DataTrigger Property="IsEnabled" Value="False">
       <Setter Property="Opacity" Value="0.5" />
    </DataTrigger>
  </Style.Triggers>
</Style>

#2


0  

If you're running the long running validation operation on the UI thread, you're locking up the UI and it can't update Visuals until the validation is complete. By that time you've already re-enabled the controls. If the operation is long enough that the user would notice it should be done on a background thread.

如果您正在UI线程上运行长时间运行的验证操作,那么您将锁定UI,并且在验证完成之前无法更新Visual。到那时你已经重新启用了控件。如果操作足够长,用户会注意到它应该在后台线程上完成。