I've come across a strange scenario where a frame refuses to refresh its content.
I can kinda understand what's happening but the solution is not coming to me.
I have a page that has a frame (Frame1) and several buttons. When I click on a button a page is loaded into the frame. This works perfectly in most situations.
Private Sub btnIncidents_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnIncidents.Click
Frame1.Source = New System.Uri("/Incident/Incidents.xaml", UriKind.Relative)
End Sub
However, I have a situation where I need to select the button that was previously clicked to effectively do a Refresh on the Uri. The problem is it simply does nothing because the Uri hasn't changed. That makes sense but it's not what I want, I need to call it again.
My first solution was to introduce Frame1.Refresh which initially did the trick. But once a page was Refreshed, none of the Buttons could load a different page.
It was as if by calling Frame1.Refresh I'd broken the Frames ability to navigate to other pages.
My second idea was to set the Frame source to Nothing (Null) and then set the source to the URI but that didn't work either. ie Frame1.Source = Nothing
Has anyone else come across this or maybe have some suggestions? I just need to Refresh/Reload the Frames page without breaking the Frame!
I had the similar problem - with html though. Resolved it with
frame.NavigationService.Refresh();
apparently will clear navigation history, but in my case I do not really care.
Got the answer from http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8fc6bd83-2803-4820-a22b-d4d87638c4e2
Related
First some explanation:
I am attempting to make (what should be) a simple offline "character generator" for a game I am working on. I am using VB for this and I am still a beginner. I have created a WinForms application in VS 2012 and created a local database object to hold various data. Within the database I have a 'Players' table to hold all the data. I have also added a BindingNavigator to the form, yet I removed all but the add and delete buttons as navigation is controlled by a List control which is bound to the PlayersBindingSource. I also added a save button to the BindingNavigator.
I manually populated the 'Players' table with two example entries to work with and, when the form loads, the listBox displays the two entries by their 'Player Name' field correctly. When one is selected all the controls representing each field change accordingly. If I change any values and hit the save button, it seems to work with the code I'm using.
Now the problems:
When the add button is pressed, it makes a new entry in the ListBox, yet none of the default values specified are showing up. If I edit this entry and then hit save it seems to update fine. However, if I make any other changes to any of the entries and try to save, it throws an exception.
When the delete button is pressed, the entry disappears from the list as expected, but again, if I try to save, I get an exception.
here is the code that is in my form thus far (not much):
Public Class frmMain
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.PlayersTableAdapter.Fill(Me.DatPlayerDataSet.Players)
End Sub
Private Sub SaveToolStripButton_Click(sender As Object, e As EventArgs) Handles SaveToolStripButton.Click
Me.Validate()
Me.PlayersBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.DatPlayerDataSet)
End Sub
End Class
Also, if I look at the data contained in the 'Players' table, the two example entries remain unchanged, and no additional entries are added, so I don't think the edits were never actually committed to the table.
If anyone can help me with this, or could even simply provide a link to some tutorials that would help me, I would be highly appreciative. I have browsed this site, and microsofts msdn library, searching for information about data binding and navigation, yet I couldn't seem to find anything that helped.
You want do one more think in "btnNewPlayer_Click" sub after insert row, clear the list and re load the list items or call the function which you are using to fill the list items.
Try refreshing the page, the list might get updated.
Think about a WPF program that has 2 pages which you navigate between. (Upload and Crop)
In the first page, you load an image using a button, select the image, and your image appears in the WPF Image control. Then, you press the "Crop" button. That sends the navigation to the second page, which you can crop the image.
Then, you crop the image in the second page. Then you press "next". Next button must redirect you to the first page, but wait a minute, the image you loaded no longer exist in the page. Because it's a new page.
Dim CropPage As New Crop(Crop_Bmp, Crop_BmpSource)
Me.NavigationService.Navigate(CropPage)
You may think it's okay. Because we pass the parameters and we can refill the WPF Image controls using that parameters. But, there is actually 8 upload panels in the page 1. So, other ones are important.
Or think about another method I found. Instead of using a new page instance, navigate back that you used.
Upload.Crop_Bmp = Crop_Bmp
Upload.Crop_BmpSource = Crop_BmpSource
Me.NavigationService.GoBack()
Upload.Crop()
But in the second one, it throws errors.
"Reference to a non-shared member requires an object reference."
Then, back to the Upload page, I made the variables and functions "Shared". But then, more problems come up. Because you cannot edit the local variables unless you also make them Shared. So, all of the variables and functions need to be "Shared".
I'm searching about a solution for a few days and I could not get rid of them. What method should I use? Redirecting back, or opening a new instance?
In old-type applications, it was very easy. All was that:
Form1.Crop_Bmp = Crop_Bmp
Me.Hide()
Form1.Crop()
And it was working perfectly. Because the forms were not instances like WPF pages. That's the reason I find WPF quite weird.
I found it a way to do this. When navigating to the Crop page, I sent the Upload page as a parameter to Crop Page.
Dim CropPage As New Crop(Crop_Bmp, Crop_BmpSource, Me)
Me.NavigationService.Navigate(CropPage)
Then, in Crop:
Public Sub New(ByVal Crop_Bitmap_ As Bitmap, ByVal Crop_BitmapSource_ As BitmapSource, ByVal pg As Upload)
' This call is required by the designer.
InitializeComponent()
UploadPage = pg
Then, in the Crop page, I accessed that parameter to modify its elements. For example:
Me.NavigationService.Navigate(UploadPage)
UploadPage.Crop()
This sounds like a bad use-case for the Pages metaphor. Pages are for loosely coupled peer screens (E.G. A separate page for each department), but you are using them in a tightly coupled parent-child relationship. (The "Crop" page is the child of the "Upload" page) For what you are doing, launching the crop screen as modal dialog might be more fitting.
If you want to keep everything in the same window, you can keep both functions in the same window, and toggle their visibility as needed.
I am using a C1ReportViewer control, and have already posted a question on the C1 forums, however i thought i would post here as well to see if anyone had run across a similar issue. The control uses the generic silverlight PrintDocument() method.
When printing a Crystal Report from this control in Silverlight 5 sometimes the report prints out garbled, meaning different sized text, tapered lines and generally out of position. It also rarely prints the entire report.
I have narrowed the issue down to a few printers, and only with machines using their 32 bit drivers. Based upon this, and the changes made to Silverlight 5, i am assuming the issue revolves around PostScript compatibility. However, as our product is LOB application, enforcing PS compatible printers and printer drivers is nearly out of the question.
Accordingly, if this is indeed a post script issue, based upon the documentation for silverlight 5, the PrintDocument() method should be failing back to the default bitmap method. See Am I correct in understanding that vector printing in SilverLight 5 will only work with a Postscript printer?
My question for stackoverflow is: Has anyone encountered a similar issue in with printing in Silverlight 5, or has anyone had success printing Crystal Reports/PDFs? And in the off chance that anyone has, what solutions have you come up with?
Much Appreciated,
Greg
I was able to come up with a solution for this. Instead of using the built in C1 Printing functionality I was able to write some code to force bitmap printing.
First i created a new PrintDocument, and hooked up some handlers for its PrintPage event.
mobjPrintDocument = New PrintDocument
RemoveHandler mobjPrintDocument.PrintPage, AddressOf Print_Report
AddHandler mobjPrintDocument.PrintPage, AddressOf Print_Report
Then we can call the PrintBitmap function on the PrintDocument whenever you want to print. Here I am doing it when the user clicks the Print button.
Private Sub xbtnPrint_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
mintPageIndex = 0
mobjPrintDocument.PrintBitmap(FileName)
End Sub
Now comes the important part. We can hijack the content targeted by hooking into the PrintPage event (as handled above). I can set the e.PageVisual to any visual xaml element and the PrintBitmap will handle it. Here I use the GetPages function and loop through to make sure I print each page (a pdfviewer element). However, you can point it to any visual element like I said.
Private Sub Print_Report(sender As System.Object, e As PrintPageEventArgs)
e.PageVisual = xobjReportViewer.GetPages(mintPageIndex)
mintPageIndex += 1
e.HasMorePages = mintPageIndex < xobjReportViewer.GetPages.Count
End Sub
The e.HasMorePages allows you to force the firing of this event until you are finished.
Hope this is helpful to someone. With Silverlight 5 and the Post-Script printer support, alot of printers that have a PostScript emulator may not be compatible, but will also not default to bitmap printing. This workaround fixes that, making printing a little bit more stable in a LOB type application.
I'm setting a global variable to null before navigating to the mainpage and in the mainpage I check to see if that variable is null of not, but It isn't.
It seems to be behaving correctly when I slow down the execution using breakpoints.
Otherwise Doing a
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
straight after setting something in app just makes that not work.
Are there any considerations that I am missing, because I fear that the issue could be anywhere in the app (i've looked for anything that sets it back, and there's also nothing running in between Navigate and it landing on MainPage
You could try using on the mainPage, OnNavigatedFrom page event and under that change the value to Null. Also Handle your app with Tombstoning appropriately and back up persistent Data, Even have it load that Persistent Data when you navigate to a new page and then check to make sure that valued reference is Null.
I do hope this helps you, i have recently had an issue similar.
Is there any way to detect 302 redirects within the web browser control that I don't know of? Maybe some kind of magic with the underlying unmanaged control?
No, it's not possible with the normal WebBrowser control. Doing anything with the underlying unmanaged control looks very complex, if that's what you're after you could have a look at
http://www.codeproject.com/KB/miscctrl/csEXWB.aspx though:
csEXWB is a C# .NET 2.0 control that
creates, hosts and sinks the events of
the original Webbrowser control (Not
.NET or any other wrapper). Advanced
customization and total control over
the Webbrowser control are achieved
via implementation of a number of
interfaces, along with the addition of
many methods, properties, events and a
COM library.
That includes being able to view page headers, which is what you'd need to do to detect the HTTP redirect.
I was able to detect the redirect within the NavigateError event. The statuscode will be 301 or 302. I set a flag that a redirection is to occur. Then in the navigatecomplete2 event, the URL is the redirection URL. In that event handler I check my redirection flag, and if true, clear the redirect flag and navigate again to the new URL. This should work for multiple redirects. This is VB6 code, but should work in theory for any WebBrowser implementation.
Dim m_isRedirected as boolean
...
Private Sub WebBrowser1_NavigateComplete2(ByVal pDisp As Object, URL As Variant)
If m_isRedirected Then
m_isRedirected = False 'clear the flag in case another redirect occurs
WebBrowser1.Navigate2 URL
End If
End Sub
Private Sub WebBrowser1_NavigateError(ByVal pDisp As Object, URL As Variant, Frame As Variant, StatusCode As Variant, Cancel As Boolean)
If StatusCode = 301 Or StatusCode = 302 Then m_isRedirected = True
End Sub
I found a nice workaround...
what you can do is capture/overload the webbrowser.OnNavigating and OnNavigated events.
Normally when navigating both the OnNavigating and OnNavigated events get called.
However whenever a redirect occurs the OnNavigated is called, but NOT the OnNavigating event.
so basically I'm using a counter that is reset in the OnNavigating event to 0.
in the OnNavigating i'm increasing the counter by 1.
in the OnDocumentCompleted event i will check the counter:
if counter == 1, no redirect occured
if counter> 1, redirects have occured.
so far this trick seems to work for me.
Using the WebBrowser control in WPF, you can look for the Navigating event. That won't give you the status codes, but you can see the URLs that the web browser is redirected to, so should be able to figure out when a redirection happens. I'm not that familiar with WinForms, but it may well work in a similar fashion.
private void Browser_Navigating(object sender, NavigatingCancelEventArgs e)
{
System.Diagnostics.Trace.WriteLine(e.Uri);
}