我有一个Window
包含几个按钮。我需要跟踪何时按下按钮(MouseDown
)-启动操作-以及何时释放或离开(MouseUp
或MouseLeave
),结束/取消操作。
取消可能需要一段时间,在此期间,我需要防止用户单击另一个按钮。这是忙碌指示的典型情况。我可以在操作结束时显示一个覆盖全局的忙碌指示器。然而,可用性明智的有一个更好的解决方案,但我正在努力寻找一种方法来实现它。
所以我想实现的是:
1)初始窗口状态:
2)一旦按下按钮,窗口的其余部分应该变灰(或模糊效果)并被“禁用”。窗口的其余部分还包括其他几个输入控件(TabControl
,带有Button
的通知视图,ToggleButton
等)。--都需要禁用。所以它实际上是“除了被点击的那个Button
之外的所有子节点”))
3)当按钮被释放时,操作被取消,但由于这可能需要一段时间,忙碌指示应该显示在按钮中(我知道如何做 * 这 * 部分)
4)一旦操作结束,窗口就会恢复到初始状态:
有两个重要条件:
- 有相同类型的其他按钮(相同的功能&行为)在同一
Window
.因此,仅仅将Panel.ZIndex
设置为 * 常量 * 是行不通的。 - 在同一个窗口中有几个其他的输入控件。这些也需要“禁用”。
- 显示覆盖/灰出其余的
Window
可能不会触发鼠标事件像MouseUp
或MouseLeave
(否则该操作将立即被取消).
研究完成
关闭窗口:我使用IsEnabled
属性进行了研究。但是,默认情况下,它会传播到所有子元素,您不能重写某个特定子元素的值。我实际上已经找到了一种方法来改变这种行为(在SO上),但我担心改变这种行为可能会在其他地方搞砸(而且,这真的是出乎意料的-未来的开发人员会认为它是魔术)。此外,我不喜欢如何控制看起来在禁用状态,并与这将是非常混乱的工作。
所以我更喜欢使用某种“叠加”,但它会使后面的东西变灰(我猜color=grey, opacity=0.5
与IsHitTestVisible=True
结合将是一个开始?但是这里的问题是,我不知道如何让 * 一 * 按钮的顶部覆盖,而所有的窗口的其余部分留在后面.
编辑:使用ZIndex似乎只对同一级别的项目有效(至少在网格中)。所以这也不是一个选择:(
3条答案
按热度按时间qojgxg4l1#
很有趣的问题。我试着像下面这样解决它:
1.使用唯一标识符在您的按钮上定义
Tag
属性(我使用了数字,但如果您将Tag设置为按钮所做的事情,则会有意义),并像下面这样定义Style
:1.然后捕获在VM中调用Command的按钮的Tag,如下所示(这里我已经在后面的代码中定义了所有属性)
1.最后是转换器,如果这个按钮引发了命令或正在执行某些操作,
我使用Backgroundworker模拟了繁重的工作,并使线程睡眠300毫秒。测试过了,工作正常
rkttyhzu2#
因此,经过一番深思熟虑,我认为它可能是更好的,只是添加一个覆盖在装饰层-周围的控制。我发现有人已经这样做了,所以我的解决方案在很大程度上基于这项工作:http://spin.atomicobject.com/2012/07/16/making-wpf-controls-modal-with-adorners/
这是我的装饰品(如果你有更好的名字,欢迎你的建议!):
此
Adorner
需要添加到顶部AdornerLayer
。Window
有一个(至少是它默认的ControlTemplate
.)。或者,如果您只想覆盖某个部分,则需要在那里添加AdornerLayer
(通过在UIElement
周围放置AdornerDecorator
),并在那里将Adorner
添加到AdornerLayer
。**还没有工作:**当我在
Loaded
事件处理程序中添加Adorner
时,装饰器没有正确绘制(有点太小)。一旦窗口调整大小的装饰适合完美。我将不得不在这里提出一个问题,以找出是什么原因造成的。rkkpypqq3#
所以,经过一番折腾和思考,我得到了一个工作解决方案(“原型”):
Rectangle
Opacity=0.5
和Background=White
,覆盖整个Window
grid
)Canvas
,它也覆盖了整个Window
,并且在Rectangle
之上。这是用来托管被点击的按钮Panel
中删除并添加到Canvas
中。Canvas.Left
、Canvas.Top
、Width
和Height
Panel
(在相同的索引处)。首先,让我们从视图(Window.xaml)开始:
注意:由于这只是一个原型,我没有使用MVVM,...所以事件处理程序在
MainWindow.xaml.cs
后面的代码中:注意:我选择使用
IDisposable
。很多人可能不喜欢。然而,它清楚地表明,它需要恢复(处置),我可以有FxCop警告我,如果有人不这样做;- ).下面是魔术的实现:
public class FormData { private; private readonly Panel _originalParent; private readonly Point _originalSize; private readonly Canvas _Bulletin = new Canvas();
感谢大家的参与!