c# - Adorner as popup not working -
i tried create popup in wpf using adorner can greyout background. idea accept kind of uielement, greyout , lock others (like showdialog in forms), , show uielement.
it based on tutorial website.
i have 1 class called popup:
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 idisposable; } private popup(uielement parentparentelement, uielement childelement) : base(parentparentelement) { _childelement = childelement; if (childelement != null) { addvisualchild(childelement); } getfocus(this); } protected override int visualchildrencount { { 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 main window"); } var transformtoancestor = this.adornedelement.transformtoancestor(_window); var windowoffset = transformtoancestor.inverse.transform(new point(0, 0)); // point of lower-right corner of 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); } }
this class adorner magic , draws uielement on top of first or default grid inside current window.
i created static class 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); }}
that uses extension methods allow uielement close , show.
everything seems work ok window (and other elements) can still used keyboard. tried using isenabled = false makes little ugly, i'm trying have same effect showdialog().
second problem when popup opens popup parent freezes , doesn't accept input (nothing does..).
i hope can me. maybe adorners aren't best idea , if has suggestions or better ideas please share.
here simple example of overlay doesn't require adorner
s.
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 normal xaml here --> <rectangle fill="#7fffffff" visibility="{binding yourboolproperty, horizontalalignment="stretch" verticalalignment="stretch" converter={staticresource booleantovisibilityconverter}}" /> </window>
in code:
// show overlay yourboolproperty = true;
...
// hide overlay yourboolproperty = false;
Comments
Post a Comment