I am using a transparent borderless WPF window to get around some drawing limitations of my ESRI ArcEngine which is displayed in a WindowsFormHost in a WPF window. When I move the my app window, I want to move the transparent window at the same time. Is there a way to snap these two windows together so they move together?
There is no facility for "snapping" windows together per se but you can accomplish the same thing very effectively by event handling:
handle the size change event of the parent window
handle the location change event of the parent window
For any of the above-listed events:
update the size and location of the child window to that of the parent window
It sounds hacky, and it is, but works pretty seamlessly. Windows size and move events fire often enough that your windows will look glued together.
Related
I have a WPF application running on a Win10 desktop using the new (Microsoft.Toolkit.Wpf.UI.Controls.WebView v5.0.0.0) WebView control in a dialog window. The first time this dialog window is created, WebView navigation successfully completes but most of the time the WebView stubbornly continues to display a blank page.
If I minimise that first instance of the dialogue window and restore it, the content is instantly rendered. If I close that window instance and create a new one, the control generally renders as expected.
Changing the WebView.Visibility in code to Collapsed and then back to Visible on navigation completion doesn't fix the blank page.
Has anyone seen this behaviour? Does anyone have a solution to provoke WebView to actually render?
In theory the new WebView is a better architectural option than reverting to the old WebBrowser so I'm loathe to go down that path.
Additional detail
Windows 10 desktop, x64, targeting .NET 4.6.2, WPF 4.x.
The WebView instance is defined in XAML (without a Source binding) inside a UserControl.
The UserControl is embedded in a window defined in XAML, which only contains a root level Grid to contain the UserControl.
That window is shown via ShowDialog().
Source navigation is performed in code behind controlled by the current selection of a TabControl.
The WebView is NOT defined in the TabControl item template (doing so throws exceptions most of the time on tab selection change). It is in a container that is a sibling to the TabControl.
The NavigationCompleted event reports success.
I found that attempting to minimise and then restore the containing window in code didn't fix it, despite minimise & restore working when the user does it. Invalidating the control layout or visual or arrange didn't work. Maximising and restoring the window in code did, but is visually annoying, but it led me to two reasonable workarounds:
Configure the WebView.Visibility to be Collapsed in XAML and either:
handle the UserControl.Loaded event and set the visibility to Visible; or
handle the WebView.NavigationStarting event and set it to Visible.
Those are easiest if starting out collapsed won't cause unacceptable visual disruption. Getting in early via the Loaded event helps. Starting out Hidden doesn't work.
Leave WebView.Visibility configured to Visible in XAML, handle the WebView.NavigationStarted event in the UserControl, and then if it's the first time the handler called in this process do something like this to cause the control to resize and then restore the original size:
var height = Height;
Height = 0;
Application.Current.Dispatcher.BeginInvoke(
(Action)(() => { Height = height; }),
DispatcherPriority.Input
);
Dispatching the value restoration seems to be required (although maybe calling something like InvalidateLayout() in between would suffice).
In Winforms if the MDI child window is maximized it doesn't receive ResizeBegin (or ResizeEnd) events. It does receive Resize events - why the distinction? If the child isn't maximized it does get ResizeBegin/End events. Is there a nice way around this? There are plenty of ugly ways: calling directly from the MDI container ResizeBegin event to the child for example.
The ResizeBegin/End events are generated when the user starts and stops resizing a window. Implemented by a modal loop inside Windows itself, it keeps the window edge following the mouse cursor when the user moves it. ResizeBegin when he clicks a window edge, ResizeEnd when he releases the mouse button.
Clearly no user is involved when you change the Size or ClientSize property of an MDI child window in your code. So no Begin or End, just the Resize event. And just one Resize event trigger, there's no constant train of them like there will be when the user uses the mouse to resize. Which otherwise explains why Begin/End is important, if you do a lot of work in your Resize event handler then you'll bog down the UI pretty heavily. Common with automatic layout, the visible artifacts are not pretty.
If you really have to then you can simply generate the event yourself. Call OnResizeBegin() before, OnResizeEnd() after you change the window's Client/Size property value. That code needs to live inside the window you resize to get the correct event triggered. Pretty unlikely you should be doing this btw. Do beware that MDI automatically resizes an maximized MDI child window, it of course cannot be maximized anymore when you activate another one. You can't wrap that with OnResizeBegin/End() calls.
I've read articles that Child Windows in SL3 cannot be set to non-moveable, without creating your own custom window. Was this fixed in SL4? This is a problem, because the user is able to drag windows off the silverlight stage, which seems like an awkard UI design. On my first try I moved it offscreen and was not able to move it back or close it. I do not understand the logic behind leaving out the option to make the window non-moveable.
Is there any other way to prevent the user from dragging a child window off the screen? Or is creating my own custom window the only way.
I created my own custom Style which gets rid of the close button in the header and stops the moving.
In your control set: <controls:ChildWindow ... Style="{StaticResource themeChildWindowStyle}"
You can create the style with Blend pretty easy.
Here's a discussion on this topic which has another solution from "friendy1108" ~"My solution right now is to hide the title bar and make a button to close the child window.
From the link you sent, I can do this: title.Visibility = Visibility.Collapsed;" That would do it, but I prefer the style override.
I have a window with a popup that pops when an item in a listview is double clicked.
It centers to the main window and looks really nice floating there.
The problem is when the user moves the main window or selects another program, and the popup floats on top of other stuff.
I would like to have something like a popup, meaning that it floats on top of other elements in the window, but sticks with the main window when it moves (stays centered), and doesn't float on top of other programs.
Can I make a popup act like this, or is there a better way to do it?
Popups will not move while the window is resized or moved. Because, Popups/Context menus are not the part of Visual Tree. You have to use Adorner for this. I will suggest to read this four part series for a quick start on Adorner.
It's possible that an Adorner will fit your needs in this case better than a popup. Adorners can float above your window, too. There are a few differences, mainly that an adorner is bound to a UIElement (which include windows).
If you are willing to use a third-party/open source (MS-PL) option, the Extended WPF Toolkit has a ChildWindow control.
It's technically not a separate window, but it appears to be a separate window to the user.
I have not found a way to make Popups stop doing that in WPF
As an alternative, you can create a UserControl which acts like a Popup.
Usually I host the content section of the app along with the Popup within a Canvas control, and when IsPopupOpen gets changed to True I set the popup Visibility = Visible.
I would like to have a form which has a few controls as transparent overlays over a bitmap. This bitmap is subject to transform matrix (zoom & scroll). I'm trying to achieve a look similar to GoogleMaps where the controls do not move when the background image is panned/zoomed.
I've tried to mimic this in my OnPaint. However, when the window is scrolled only the newly exposed area gets invalidated so my control doesn’t repaint.
I've tried to calculate where the old control was, invalidate that area, and also invalidate the area where it's supposed to have been. When I do this it flickers and you can still see the image as its scrolled.
I tried to put a ButtonControl on my display window. However, it always scrolls with its parent control. I tried to capture the scroll events and then adjust the position of the ButtonControl. This also has a delay update effect so it looks not so good.
Any ideas would be greatly appreciated.
It sounds to me like you need to Invalidate() your control wich handles the OnPaint event.
Unfortunately, you get the flicker because the Auto-scrolling mechanism sets its position, and then you restore it. The result is two messages being sent to the button.
Place your bitmap and scroll logic in a separate control that fill the entire form. That means both your bitmap control and the button are child controls of the form.
Alternatively, draw the button yourself. You will then of course need to do some work on getting it to respond to mouse clicks etc. The ControlPaint class has methods that help you mimic the appearance of Windows controls.