I'm using Silverlight 4 to print but I would like some sort of progress bar or busy indicator.
I've tried to using a progress bar but it is not really working. The 2 issues I have are:
the progress bar does not indicate progress, I have IsIndeterminate=True, but it does not animate when printing starts (Print dialog's Print button is clicked)
the progress bar visibility is not being set at the proper time, depending upon where I put the code to set visibility it displays either too soon (before print is clicked) or too late (after printing has worked for awhile)
I'm guessing, but I think the reason for the above is because when the print dialog is displayed Silverlight has handed off control to the OS for prining(??).
I tried using a dispatcher invoke but I get a security exception (dialog can only be displayed from user click).
Any ideas on how to deal with either of the above issues?
thanks.
Create a BusyIndicator in your XAML, it's a part of the Silverlight Toolkit. And then during the BeginPrint event set the BusyIndicator's IsBusy to True. Also during EndPrint set IsBusy back to false.
var docToPrint = new PrintDocument();
docToPrint.BeginPrint += (s, args) =>
{
MyBusyIndicator.IsBusy = true;
MyBusyIndicator.BusyContent = "Printing...";
};
docToPrint.PrintPage += (s, args) =>
{
args.PageVisual = this.MainCanvas;
};
docToPrint.EndPrint += (s, args) =>
{
MyBusyIndicator.IsBusy = false;
MyBusyIndicator.BusyContent = "";
};
Related
I have an issue with Winforms and touch inputs via a Microsoft Surface tablet. I know that winforms does not support touch input, but maybe there is something there can be done about this. So in my Winforms application i have a Form with two controls. A simple List Box and CefSharp ChromiumWebBrowser Control.
When I open the application the HTML is loaded and everything works fine with normal mouse input. I can click the textboxes and I can type. But when i do the same thing with touch controls on a MS Surface it seems the the ChromiumWebBrowser Control dows not get focus. The HTML Textboxes inside the Browser have focus, but the ChromiumWebBrowser Control does not. So whem i type, no input is send to the textboxes.
I tried to set focus manually whit C# in winforms, but those click events do not get fired in touch mode except for the Enter event. But this is fired only once. So i dont know how to get around this.
The user needs to be able to click outside the Browser Controle and do something there and then get back to the Browser and type into those textboxes.
Maybe someone had a similar issue and knows a workaround. If other Info is needed, please tell me.
Here is a gif to illustrate, hope it helps: https://i.stack.imgur.com/8J0EZ.gif
Thanks
private void Form1_Load(object sender, EventArgs e)
{
var asForm = System.Windows.Automation.AutomationElement.FromHandle(this.Handle);
wbMap = initBrowser();
this.panel1.Enabled = true;
this.panel1.Controls.Add(wbMap);
wbMap.FrameLoadEnd += WbMap_FrameLoadEnd;
wbMap.Click += WbMap_Click;
wbMap.Enter += WbMap_Enter;
wbMap.MouseClick += WbMap_MouseClick;
wbMap.DoubleClick += WbMap_DoubleClick;
wbMap.Leave += WbMap_Leave;
wbMap.LostFocus += WbMap_LostFocus;
wbMap.GotFocus += WbMap_GotFocus;
wbMap.PreviewKeyDown += WbMap_PreviewKeyDown;
}
private ChromiumWebBrowser initBrowser()
{
ChromiumWebBrowser wbMap = new ChromiumWebBrowser();
BrowserSettings browserSettings = new BrowserSettings();
browserSettings.FileAccessFromFileUrls = CefState.Enabled;
browserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
wbMap.BrowserSettings = browserSettings;
wbMap.LoadHtml("<!DOCTYPE html><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><head><meta charset=\"utf-8\" /><title></title></head><body><input type=\"text\"><input /></body></html>");
wbMap.Dock = DockStyle.Fill;
return wbMap;
}
private void WbMap_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
Console.WriteLine("QGIS_WbMap_FrameLoadEnd");
}
I have a very odd problem:
In my C# code, if I set the "Topmost" property, the window does not stay on top.
However, if I toggle this same property in Snoop, the windows stays on top.
My question is this: what is Snoop doing to force the window refresh?
What I have tried
I have tried the following:
window.UpdateLayout();
window.InvalidateVisual();
Adding a background task to continuously set this property.
Setting TopMost to false, then true, to trigger a DependencyProperty refresh.
It turns out that Snoop was not doing anything special.
If I wait an additional 500 milliseconds, then it works:
Task task = Task.Run(
async () =>
{
// Without this delay, the change will not work.
await Task.Delay(TimeSpan.FromMilliseconds(500));
Application.Current.Dispatcher.Invoke(
() =>
{
floatingPaneWindow.Topmost = true;
{
if (window.Top < 0)
{
window.Top = 0;
}
if (window.Left < 0)
{
window.Left = 0;
}
}
});
});
Of course, adding specific times into an application is very hacky, so I'm currently looking for some method to determine if the window is properly set up.
Update
Puzzle solved, use the Dispatcher select an appropriate priority, see WPF: In an attached property, how to wait until visual tree loaded properly?
I have an application that’s running silently in the System Tray. Occasionally, I need it to pop-up a small notification form to the end-user.
I’ve attempted to accomplish this w/ a WinForms application that has the bulk of its logic built into a hidden form that’s not displayed to the user. Then, when certain criteria is met, I display a secondary form to the user.
My problem is, this secondary form isn’t always on top, even when I set TopMost = true.
I believe this is because the main form isn’t being displayed, so its child forms can’t take advantage of TopMost = true. I've tried moving TopMost around to a few different places. Any other ideas?
MainForm logic:
ChildForm childForm = new ChildForm(this);
int x = (Screen.PrimaryScreen.Bounds.Width / 2) - (childForm.Width / 2);
childForm.StartPosition = FormStartPosition.Manual;
childForm.Location = new Point(x, 0);
childForm.ShowDialog();
//childForm.TopMost = true;
ChildForm logic:
public ChildForm(MainForm mainForm)
{
InitializeComponent();
//this.TopMost = true;
}
After stepping into some breakpoints, I realized that the childForm will be TopMost as long as I set that property after the childForm has been initialized properly and shown. I was able to force this to work by setting the TopMost command within the Shown event like this:
private void ChildForm_Shown(object sender, System.EventArgs e)
{
this.TopMost = true;
}
I'm building a user control that includes a flyout panel.
When I click the button to open the panel I'm trying to capture the mouse so that I can detect if the user clicks off the flyout panel so I can close it.
But right after I capture the mouse, I get a lost mousecapture event and I can't detect the clicks outside of the panel.
here is where I detect the straight open close click
private void Grid_MouseUP(object sender, MouseButtonEventArgs e)
{
if (indicatorVM != null)
{
if (indicatorVM.SettingsFlyoutVisibility == Visibility.Collapsed)
{
doRelease = false;
indicatorVM.SettingsFlyoutVisibility = Visibility.Visible;
bool result = this.CaptureMouse();
result = Mouse.Capture(this, CaptureMode.SubTree);
}
else
{
doRelease = true;
indicatorVM.SettingsFlyoutVisibility = Visibility.Collapsed;
this.ReleaseMouseCapture();
}
}
}
If I wire into the capture lost event, it's hit immediately after the flyout opens. When I check the result variable, regardless of how I capture the mouse, the result is true, so it appears to be working correctly.
Any ideas?
First, try an UpdateLayout right after setting indicatorVM's visibility to Visible, before you capture the mouse. This will avoid having the layout change after you capture the mouse, which is probably what is stealing the capture from you. My second suggestion is to slightly postpone the capture with a Dispatcher Invoke, like this:
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate()
{
bool result = this.CaptureMouse();
result = Mouse.Capture(this, CaptureMode.SubTree);
});
The capture will then be after the layout consequences.
I have a WPF app, upon clicking a button, the app goes into a calculation that can take 4-10 seconds. I'd like to update the opacity of the background and show a progress bar, during that operation.
To do that, I use this code:
this.Cursor = System.Windows.Input.Cursors.Wait;
// grey-out the main window
SolidColorBrush brush1 = new SolidColorBrush(Colors.Black);
brush1.Opacity = 0.65;
b1 = LogicalTreeHelper.FindLogicalNode(this, "border1") as Border;
b1.Opacity = 0.7;
b1.Background = brush1;
// long running computation happens here ....
// show a modal dialog to confirm results here
// restore background and opacity here.
When I run the code, the background and opacity doesn't change until the modal dialog appears. How can I get those visual changes to happen right now, before the calculation begins? In Windows Forms there was an Update() method on each control, that did this as necessary, as I recall. What's the WPF analog?
What if you would do long running computation in the background thread? Once they are done dispatch results back to UI thread...
Honestly, I suspect there is nothing else there, that can solve your problem. Maybe nested pumping will do the trick, but I really doubt it.
Just in case this reference is helpful: Build More Responsive Apps With The Dispatcher
Use the DoEvents() code as shown here:
http://blogs.microsoft.co.il/blogs/tamir/archive/2007/08/21/How-to-DoEvents-in-WPF_3F00_.aspx
My actual code:
private void GreyOverlay()
{
// make the overlay window visible - the effect is to grey out the display
if (_greyOverlay == null)
_greyOverlay = LogicalTreeHelper.FindLogicalNode(this, "overlay") as System.Windows.Shapes.Rectangle;
if (_greyOverlay != null)
{
_greyOverlay.Visibility = Visibility.Visible;
DoEvents();
}
}
private void DoEvents()
{
// Allow UI to Update...
DispatcherFrame f = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new Action<object>((arg)=> {
DispatcherFrame fr = arg as DispatcherFrame;
fr.Continue= false;
}), f);
Dispatcher.PushFrame(f);
}