我尝试使用装饰器在WPF中创建一个弹出窗口,这样我就可以将背景灰化。其思想是,它将接受任何类型的UIelement、灰色化和锁定所有其他(比如表单中的showDialog ),并显示uielement。
它基于本网站的教程。
我有一门课叫做弹出:
class PopUp : Adorner, IDisposable
{
private static readonly Brush _screenBrush = new SolidColorBrush(Color.FromArgb(0x7f, 0x7f, 0x7f, 0x7f));
private static UIElement _childElement;
private static Window _window;
private AdornerLayer _layer;
public static IDisposable Overlay(UIElement childElement)
{
_window = Application.Current.MainWindow;
var grid = LogicalTreeHelper.GetChildren(_window).OfType<Grid>().FirstOrDefault();
var adorner = new PopUp(grid, childElement) { _layer = AdornerLayer.GetAdornerLayer(grid) };
adorner._layer.Add(adorner);
return adorner as IDisposable;
}
private PopUp(UIElement parentParentElement, UIElement childElement)
: base(parentParentElement)
{
_childElement = childElement;
if (childElement != null)
{
AddVisualChild(childElement);
}
GetFocus(this);
}
protected override int VisualChildrenCount
{
get { return _childElement == null ? 0 : 1; }
}
protected override Visual GetVisualChild(int index)
{
if (index == 0 && _childElement != null)
{
return _childElement;
}
GetFocus(this);
return base.GetVisualChild(index);
}
protected override Size MeasureOverride(Size constraint)
{
_childElement.Measure(constraint);
return _childElement.RenderSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
if (_childElement == null) return finalSize;
var adorningPoint = new Point(0, 0);
_childElement.Arrange(new Rect(adorningPoint, this.AdornedElement.RenderSize));
return finalSize;
}
protected override void OnRender(DrawingContext drawingContext)
{
_screenBrush.Opacity = 0.5;
drawingContext.DrawRectangle(_screenBrush, null, WindowRect());
base.OnRender(drawingContext);
}
private Rect WindowRect()
{
if (_window == null)
{
throw new ArgumentException("cant get main window");
}
var transformToAncestor = this.AdornedElement.TransformToAncestor(_window);
var windowOffset = transformToAncestor.Inverse.Transform(new Point(0, 0));
// Get a point of the lower-right corner of the window
var windowLowerRight = windowOffset;
windowLowerRight.Offset(_window.ActualWidth, _window.ActualHeight);
return new Rect(windowOffset, windowLowerRight);
}
private void GetFocus(UIElement element)
{
element.Focusable = true;
Keyboard.Focus(element);
element.IsEnabled = true;
}
public void Dispose()
{
_layer.Remove(this);
}
}这个类具有装饰功能,并在当前窗口中的第一个或默认网格之上绘制一个UIelement。
我创建了一个静态类PopUpExtender:
public static class PopUpExtender
{
private static Dictionary<UIElement, IDisposable> _popUps;
public static void ShowAsPopUp(this UIElement child)
{
if (_popUps == null)
{
_popUps = new Dictionary<UIElement, IDisposable>();
}
_popUps.Add(child, PopUp.Overlay(child));
}
public static void ClosePopUp(this UIElement child)
{
if (!_popUps.ContainsKey(child)) return;
var disposableChild = _popUps[child];
disposableChild.Dispose();
_popUps.Remove(child);
}}它使用扩展方法允许UIelement关闭并显示。
一切似乎都正常,但是窗口(和其他元素)仍然可以被键盘使用。我试着使用isEnabled = false,但这使它有点难看,我正试图获得与that对话框()相同的效果。
第二个问题是,当弹出打开弹出时,父程序冻结,不接受任何输入(什么都不接受.)。
我希望有人能帮我。也许装饰品并不是最好的做法,如果有人有任何建议或更好的想法,请分享。
发布于 2015-06-25 13:37:41
下面是一个不需要任何Adorner的覆盖的简单示例。
XAML:
<Window x:Class="YourApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
... >
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<!-- Define your normal XAML here -->
<Rectangle Fill="#7FFFFFFF" Visibility="{Binding YourBoolProperty,
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Converter={StaticResource BooleanToVisibilityConverter}}" />
</Window>代码:
// Show overlay
YourBoolProperty = true;..。
// Hide overlay
YourBoolProperty = false;https://stackoverflow.com/questions/31048928
复制相似问题