Try-catch not working loading XAML resource - c#

I have these pieces of code:
private void btnPlanning_Click(object sender, RoutedEventArgs e)
{
LoadPage("PlanningView.xaml");
}
private void LoadPage(string APage)
{
try
{
frameMainView.Source = new Uri(APage, UriKind.Relative);
}
catch (Exception ex)
{
string errorString = $"Resource <{APage}> not found! ";
DoLogD(errorString + " " + ex.Message);
MessageBox.Show(errorString);
}
}
Clicking on btnPlanning button, LoadPage is called passing a string with the name of the XAML resource I want to load in the frame control frameMainView.
If the given resource doesn't not exist, I would like to catch the exception and inform the user.
The problem is that when i click the button (and the resource doesn't exist), I get in any case
PresentationFramework.pdb not loaded
and a internal System.IO.IOException telling me the resource is not available.
Why my try-catch block is not working?

there are many ways to load the pages into the frame:
By setting the source
frameMainView.Source = new Uri("PlanningView.xaml",UriKind.RelativeOrAbsolute);
By setting the Content:
frameMainView.Content= new PlanningView();
By using the NavigationService:
frameMainView.NavigationService.Navigate(new PlanningView());

It´s a user interface initialization Problem. Can you get more information from the visual Studio "Output" Window?

Related

Can the Help.ShowHelp API be modified to simply invoke the CHM file?

This is my primary way for displaying help topics from within my WinForm button click handlers:
Handler:
private void buttonHelp_Click(object sender, EventArgs e)
{
CutTools.DisplayHelpTopic(this, "create-new-viewport.htm");
}
Base method:
public static void DisplayHelpTopic(Control parent, string topic)
{
try
{
// Use an empty form as the parent so that the help file will not block the CAD software
Form mHelpParent = new Form();
// Use location of this DLL file
System.Reflection.Module mod = parent.GetType().Module;
string path = Path.GetDirectoryName(mod.FullyQualifiedName);
Help.ShowHelp(mHelpParent,
Path.Combine(path, "cut-tools-help.chm"), HelpNavigator.Topic, topic);
}
catch (System.Exception ex)
{
_AcAp.Application.ShowAlertDialog(
string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace));
}
}
The forms are displaid inside AutoCAD, BricsCAD or ZWCAD. The about is fine and great. But if I want to simply display the CHM file itself (so no actual form is available) I have to do this:
[CommandMethod("TS_DisplayHelp")]
public void TS_DisplayHelp()
{
// Use location of this DLL file
System.Reflection.Module mod = GetType().Module;
System.Diagnostics.Process.Start(
Path.Combine(Path.GetDirectoryName(mod.FullyQualifiedName), "cut-tools-help.chm"));
}
It works but has one drawback. It spawns a new instance of the help and does not use the same instance.
For example:
You start one of the other commands and show the help via button click. You cancel.
You start a different command and show the help via button click. Help.ShowHelp uses same instance.
You can command and start help via TS_DISPLAYHELP and it starts new instance.
Given the context of TS_DISPLAYHELP I can't work out how to directly use Help.ShowHelp as I can in my button click handlers.
At the moment I have managed to get around this issue by duplicating the DisplayHelpTopic code directly in the command TS_DISPLAYHELP method:
[CommandMethod("TS_DisplayHelp")]
public void TS_DisplayHelp()
{
try
{
// Use an empty form as the parent so that the help file will not block the CAD software
Form mHelpParent = new Form();
// Use location of this DLL file
System.Reflection.Module mod = GetType().Module;
string path = Path.GetDirectoryName(mod.FullyQualifiedName);
Help.ShowHelp(mHelpParent,
Path.Combine(path, "cut-tools-help.chm"), HelpNavigator.Topic, "command-index.htm");
}
catch (System.Exception ex)
{
_AcAp.Application.ShowAlertDialog(
string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace));
}
}
I know that my default topic is "command-index.htm".
I am happy with the above resolution.

Multi Threading WPF C#

Still learning MVVM and multi-threading and have come across something I cannot figure out.
Users access a list of applicants via a Datagrid for their specific branch location. They can click a button within the datagrid to obtain SelectedItem to open a more detailed view of that application.
The initial time they open this view, the data is correct; however, any further time(s) they open the view the original data is still shown. It does not show the second applicants information in the View unless the application is closed and opened again.
I have read that the ViewModel is stored in memory and I thought, maybe threading would provide a solution. I used the following code to attempt just that; however, no luck.
Can someone please point me in the correct direction on how I can handle this situation, or if I am approaching this totally wrong. :)
Thank you for your time.
private void NewWindowHandler(object sender, RoutedEventArgs e)
{
try
{
Craig_Tools.Data.Globals.selectedAppID = Convert.ToInt32(appIDTextBox.Text);
Thread newWindowThread = new Thread(delegate()
{
Window tempWindow = new Window
{
Title = "Display Applicant",
Content = new Craig_Tools.ApplicationTrackingSystem.userControls.atDisplay(),
SizeToContent = SizeToContent.WidthAndHeight,
//ResizeMode = ResizeMode.NoResize
};
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
});
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error opening Applicant Display");
}
}
I have also tried the following.
private void NewWindowHandler(object sender, RoutedEventArgs e)
{
try
{
Craig_Tools.Data.Globals.selectedAppID = Convert.ToInt32(appIDTextBox.Text);
//create and show window
atDisplay newView = new atDisplay();
ViewModels.displayViewModel viewModel = new ViewModels.displayViewModel();
newView.DataContext = viewModel;
newView.Title = "Applicant ID: " + Craig_Tools.Data.Globals.selectedAppID;
newView.Show();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error opening Applicant Display");
}
}
What I have figured out using Visual Studio debugger is that the ViewModel is never executed when attempting to open the information for the second applicant. It seems to simply just grab the data that is in memory.

Awesomium The specified name (external), is reserved. WebControl exception on WPF TabItem

i am trying to create a simple WPF tabbed WebControl view using Awesomium 1.7.4.2. The idea is that I have a main ClosableTab (which extends TabItem) that contains a WebControl (let's say it HomeTab) which in turn loads a certain url. From HomeTab the user can open other tabs, ie each new web page opens at a new tab item wich contains a WebControl. Each WebControl has these handlers:
webTabControl.CertificateError += webControl_CertificateError;
webTabControl.NativeViewInitialized += webControl_NativeViewInitialized;
webTabControl.ShowContextMenu += webControl_ShowContextMenu;
webTabControl.LoadingFrameComplete += webControl_LoadingFrameComplete;
webTabControl.LoadingFrameFailed += webControl_LoadingFrameFailed;
On webControl_NativeViewInitialized I create a global javascript object called DotApi and then bind some javascript methods on it such as openTab.
There is a method called JSHandler that handles the results of DotApi methods.
When DotApi.openTab is called from HomeTab, a new tab is created, added in webTabControl (tab_control) and and then shown (if user clicked with left click).
On tabItem_loaded a new webControl is created that binds the above webControl handlers and is added as content on TabItem.
If user clicked with middle click, webControl.ApplyTemplate() is called (since middle clicks, open the new tabs in the background, ie the new TabItem doesn't get focused).
It seems quite straight-forward. This works fine almost every time. The problem is that one time in hundred it comes with this error:
The specified name (DotApi), is reserved. It either represents an HTML DOM object, or an object variable already available in the page. Use ExecuteJavascriptWithResult after DocumentReady, to obtain this object.
Parameter name: name
I noticed that the above error occurs only when the error below shows up:
A first chance exception of type 'System.ArgumentException' occurred in Awesomium.Windows.Controls.dll
I looked at debug.log and noticed that this error is similar to my error with the only difference on the specified name:
The specified name (external), is reserved. It either represents an HTML DOM object, or an object variable already available in the page. Use ExecuteJavascriptWithResult after DocumentReady, to obtain this object.
Parameter name: name
My questions are:
- Why this error occurs so rarely?
- How can it be fixed?
Below is sample code to help you understand the flow:
webControl_NativeViewInitialized
private void webControl_NativeViewInitialized(object sender, WebViewEventArgs e)
{
WebControl wbControl = sender as WebControl;
try
{
JSObject jsobject = wbControl.CreateGlobalJavascriptObject("DotApi");
// openTab will be invoked each time a new page opens in new tab
jsobject.Bind("openTab", false, JSHandler);
}
catch (Exception ex)
{
Debug.WriteLine("NativeViewInitialized exception: " + ex.Message);
}
}
JSHandler
private void JSHandler(object sender, JavascriptMethodEventArgs args)
{
try
{
if (!args.MustReturnValue)
{
case #"openTab": // parameters: url, type(order,index,map), true/fasle(focus on new tab),arguments
if (args.Arguments.Length > 0)
{
Application.Current.Dispatcher.BeginInvoke(
new OpenNewTabDelegate(OpenNewTab), args.Arguments);
}
break;
}
}
catch (Exception e)
{
MessageBox.Show("JSHandler Exception: " + e.Message);
}
}
OpenNewTab
private void OpenNewTab(JSValue[] arguments)
{
try
{
ClosableTab theTabItem = new ClosableTab(this);
theTabItem.Title = "Loading";
theTabItem.Loaded += (s_, e_) => theTabItem_Loaded(theTabItem, e_, arguments);
tab_control.Items.Add(theTabItem);
if (!(bool)arguments[2]) // whether it focus on new window or not
{
theTabItem.Focus();
}
}
catch (Exception e)
{
Debug.WriteLine("OpenNewTab exception e: " + e.Message);
}
}
theTabItem_Loaded
private void theTabItem_Loaded(object sender, RoutedEventArgs e, JSValue[] arguments)
{
ClosableTab currentTab = sender as ClosableTab;
currentTab.Loaded -= (s_, e_) => theTabItem_Loaded(currentTab, e_, arguments);
WebControl webTabControl = new WebControl();
webTabControl.Source = new Uri((string)arguments[0]);
webTabControl.CertificateError += webControl_CertificateError;
webTabControl.NativeViewInitialized += webControl_NativeViewInitialized;
webTabControl.ShowContextMenu += webControl_ShowContextMenu;
webTabControl.LoadingFrameComplete += webControl_LoadingFrameComplete;
webTabControl.LoadingFrameFailed += webControl_LoadingFrameFailed;
currentTab.Content = webTabControl;
webTabControl.Dispatcher.BeginInvoke(new Action(() =>
{
// Load the webcontrol in the backgound
if(!currentTab.IsSelected){
webTabControl.ApplyTemplate();
}
}));
}
After debugging i figured out that it was a timedOut exception from awesomium. To handle it, each time i create a webControl i set its property: SynchronousMessageTimeout = 0. If you don't set it to 0 the default value will be 800ms according to current documentation SynchronousMessageTimeout
This prevented the below exceptions from appearing:
A first chance exception of type 'System.ArgumentException' occurred in Awesomium.Windows.Controls.dl
The specified name (DotApi), is reserved. It either represents an HTML DOM object, or an object variable already available in the page. Use ExecuteJavascriptWithResult after DocumentReady, to obtain this object.
Parameter name: name

WPF disposing of view and viewmodel correctly

I've written an Outlook add-in (OL2010). It has a menu on the ribbon bar with various icons that open new windows that do stuff (hope that's not too in-depth ;)). An example of one of the icon Click handlers is below.
public void OnViewMyTracksClick(Office.IRibbonControl control)
{
try {
MyTracksViewModel viewModel = new MyTracksViewModel();
MyTracksView view = new MyTracksView();
view.DataContext = viewModel;
view.Show();
}
catch (Exception ex)
{
Log.Error("xxxxx", "Error on button click: " + ex.Message + Environment.NewLine + ex.InnerException);
}
}
In Outlook, if I click the button to open this view, I see the memory usage of Outlook.exe increase by 10mb (the window and it's accompanying data). When I close the view, none of that memory is reclaimed. If I click the button again, another 10mb is added, and again, none is released when I close the view.
I thought that this is because I'm creating a new viewmodel everytime, so I added some code to check if it was already instantiated (the view and viewmodel are now registered at the class level, rather that within the method, so that I don't create a new one each time) - _allTracksVM is an instantiation of AllTracksViewModel. _allTracksV is the view.
public void OnViewAllTracksClick(Office.IRibbonControl control)
{
try {
if (_allTracksVM == null)
{
_allTracksVM = new AllTracksViewModel();
}
_allTracksV = new AllTracksView();
_allTracksV.DataContext = _allTracksVM;
_allTracksV.Show();
}
catch (Exception ex)
{
Log.Error("xxxxx", "Error on button click: " + ex.Message + Environment.NewLine + ex.InnerException);
}
}
This didn't seem to make any difference. I then added an EventHandler that would fire when the view was closed:
_allTracksV.Closing += new System.ComponentModel.CancelEventHandler(this.view_RequestClose);
And this set both the objects to null (you can probably tell i'm grabbing at straws at this point):
void view_RequestClose(object sender, EventArgs e)
{
_allTracksVM = null;
_allTracksV = null;
}
The memory remains allocated. How can I dispose of the objects correctly (or perhaps I should be instantiating them differently), so that they don't consume another chunk of memory each time they are opened?
Thanks
Mick
Checking the VM for Null was a good idea but by setting it to null in the close handler, it is rendered useless :)
You could try to make the view a field in the containing class rather than a local variable. That way you don't need to create a new view each time.
As for the memory usage, it seems to me that you're doing it right. Since the GC only collects when necessary, it will take some time until the memoryusage declines.

Getting error "Internet Explorer cannot display the webpage" in asp.net

I have a code block that leads to a "Internet Explorer cannot display the webpage" error. When I click the submit button, with NONE of the radio buttons checked, the web page status bar displays "waiting for response from host" and then display the "Internet Explorer cannot display the webpage". When I walk through the code in visual studio, the code executes fine, and none of the catch blocks are executed.
How can I trap the error and determine why the error page is being displayed?
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
if (rbtnSearchBy1.Checked)
{
Server.Transfer("ViewEmpHistory.aspx");
}
if (rbtnSearchBy2.Checked)
{
Server.Transfer("SearchEmp.aspx");
}
if (rbtnSearchBy3.Checked)
{
Server.Transfer("ViewEmpCard.aspx");
}
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
Whatever .cs page your "btnSubmit_Click" is on, put a breakpoint on that page_load event.
Also, put a breakpoint on the page_load event of "ViewEmpHistory.aspx", "SearchEmp.aspx" & "ViewEmpCard.aspx". (so now you have four breakpoints).
Step through the project again and make sure all parameter values are being passed correctly, also make sure that you have correct logic (if applicable) for If (!PostbacK) conditions etc.
HTH
if you don't select one radiobutton it's normal that you don't enter in your catch , because your application no throw exception.
but you can view your eventlog
Enter in your cmd : eventvwr to access your event log
To debug these kind of issues, I often find it easier to use Tracing.
You can turn on tracing at the application level, or at the page level.
Your method call will then become:
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
if (rbtnSearchBy1.Checked)
{
Server.Transfer("ViewEmpHistory.aspx");
}
if (rbtnSearchBy2.Checked)
{
Server.Transfer("SearchEmp.aspx");
}
if (rbtnSearchBy3.Checked)
{
Server.Transfer("ViewEmpCard.aspx");
}
}
catch(Exception ex)
{
Trace.Warn("Exception Caught", "Exception: btnSubmit_Click", ex);
}
}
You can look at the trace log by then navigating to the Trace Viewer.
What you've done is not exactly well structured. It's cleaner if the blocks are exclusive - which is why I've added the else statements to the code below. I've also indicated where you would want to handle the state where no button is checked in comments.
But you're right, there isn't any exception being thrown. Your code didn't throw one, and when you end processing a request without returning any type of response it doesn't cause an exception.
if (rbtnSearchBy1.Checked)
{
Server.Transfer("ViewEmpHistory.aspx");
}
else if (rbtnSearchBy2.Checked)
{
Server.Transfer("SearchEmp.aspx");
}
else if (rbtnSearchBy3.Checked)
{
Server.Transfer("ViewEmpCard.aspx");
}
else
{
// Here's where the logic will flow to if no radio button is clicked.
// We could
// * Server.Transfer to a default location
// * Throw an exception
// * Do nothing, which returns no response, and causes
// IE to complain that it could not display the webpage.
}

Categories

Resources