Silverlight 3 - Out of browser HtmlPage.Window.Navigate - silverlight

Silverlight 3 allows you to run your application out of the browser, which installs a link on your desktop/start menu.
The problem is we are currently using
System.Windows.Browser.HtmlPage.
Window.Navigate(new Uri("http://<server>/<resource>"), "_blank")
to load a URL into a new browser window (it's to provide a 'print friendly' page for users to print). This works in the normal SL in-browser version, but outside the browser we get 'The DOM/scripting bridge is disabled.' exception thrown when issuing the call.
Is there an alternative which works out of the browser?
I've seen Open page in silverlight out of browser but I need to do this entirely in code, so I don't want to add a (hidden) hyperlink button and then programmatically 'click' it (unless I absolutely have to...).

you can try inheriting from HyperlinkButton and exposing public Click() method (which you can then instantiate and call from code instead of declaring it in xaml).
Details here: http://mokosh.co.uk/post/2009/10/08/silverlight-oob-open-new-browser-window/

I wrote an Extension method based on the idea to inherit from the HyperlinkButton.
public static class UriExtensions {
class Clicker : HyperlinkButton {
public void DoClick() {
base.OnClick();
}
}
static readonly Clicker clicker = new Clicker();
public static void Navigate(this Uri uri) {
Navigate(uri, "_self");
}
public static void Navigate(this Uri uri, string targetName) {
clicker.NavigateUri = uri;
clicker.TargetName = targetName;
clicker.DoClick();
}
}
Then use can use it simple, like
new Uri("http://www.google.com").Navigate("_blank");

Related

Element not found. How to test sequence of steps in multi-page WPF app with winappdriver?

I have a WPF application that features several pages. Navigation takes place after selecting some of the buttons. I am able to start the testing session successfully and to find elements in the main window. However, when clicking the "OK" button that should trigger navigation to another page, the app does not navigate and the test case fails to find UI elements in the next page. I have tried ImplicitWait and Thread.Sleep but the elements still cannot be found. It seems like the app does not navigate at all when the button is clicked.
Any ideas on how to tackle this issue? Below is what I have accomplished so far:
namespace TestDAAC
{
[TestClass]
public class UnitTests
{
protected const string WINAPPDRIVER_URL = "http://127.0.0.1:4723";
private const string DAAC_APP_ID = #"C:\Users\Admin\Desktop\VC PROJECTS\daac\DAAC\bin\x64\Release\DAAC5.exe";
protected static WindowsDriver<WindowsElement> daacSession;
[ClassInitialize]
public static void Setup(TestContext context)
{
if (daacSession == null)
{
var appiumOptions = new AppiumOptions();
appiumOptions.AddAdditionalCapability("app", DAAC_APP_ID);
appiumOptions.AddAdditionalCapability("deviceName", "WindowsPC");
daacSession = new WindowsDriver<WindowsElement>(new Uri(WINAPPDRIVER_URL), appiumOptions);
}
}
[TestMethod]
public void SequenceOfSteps()
{
daacSession.FindElementByName("OK").Click();
Thread.Sleep(5000);
// daacSession.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
daacSession.FindElementByName("New Imaging Session").Click();
}
}
}
I was able to find the reason why my test cases were not working. WinAppDriver is compatible only with Windows 10 Home or Pro. My target device runs on Windows Enterprise.

how to pass parameter to a page?

I have a page that is loaded into a frame. in the code behind, i have a string variable called mode. What i want to do is when a hyperlink is clicked, open the page and set the mode
I was hoping to do it declaratively. I tried doing
NavigatUri="myPage?mode=edit"
and then adding the following to the code behind after the initialize component call
mode = this.NavigationContext.QueryString["mode"];
But I was getting a page not found error. I have a feeling I'm on another planet. I'm new to silverlight. How do i navigate to a page in this fashion and pass that argument?
Take a look at the UriMapper in you main page. The final UriMapping would normally be the catch all that looks like this:-
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
You will note the "/" at the beginning of the Uri and the corresponding page belongs in the "/Views" folder.
Use the attribute:-
NavigatUri="/myPage?mode=edit"
make sure your page in the Views folder.
However I'm pretty sure you already have that. Your real problem is your attempt to access the NavigationContext in the execution the page constructor. Its not available at that point in the pages lifecycle. You should not attempt to use it until OnNavigatedTo is executed.
public partial class MyPage : Page
{
public MyPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
string mode = null;
if (NavigationContext.QueryString.ContainsKey("mode"))
{
mode = NavigationContext.QueryString["mode"];
}
// Do stuff with mode.
}
}
The reason you are seeing "page not found error" is thats because the Nav apps ErrorWindow just assumes any failure to load a page was because it wasn't found. Which assuming you've coded your pages correctly is probably a reasonable assumption.

How do oob silverlight application communicate through windows

If I have two windows in an oob application how do I communicate between them?
This is the new feature of silverlight 5 that allows for multiple windows.
They run in a common application. Hence they share the same static data. The scope of communication choices are therefore very large. Here is an example:-
public class MessageEventArgs : EventArgs
{
public MessageEventArgs(object payload)
{
Payload = payload;
}
public object Payload {get; private set; }
}
public class Messenger
{
private static readonly Messenger _current = new Messenger();
public static Messenger Current { get { return _current; } }
public event EventHandler<MessageEventArgs> MessageReceived;
public void Send(object payload)
{
if (MessageReceived != null)
MessageReceived(this, new MessageEventArgs(payload));
}
}
All windows can attach a handler to Messenger.Current.MessageReceived (just be sure to detach when the window closes) and any window can call Messenger.Current.Send.
Ok so you wouldn't actually use this code its a bit rubbish, the point is Windows in SL5 are not isolated. You can create whatever internal application communication mechanism you need.
Option 1: MVVM Pattern
Both windows share a reference to the same view-model. Changes made by one are seen by both.
Option 2: Normal references
Window A can how a refernce to Windows B when it creates it.
Option 3: Message Passing
You can have a global event that you subscribe to in the Load event. (Make sure you unsubscribe in the Unload event or you will leak memory!) Windows can post messages to that event which the other windows listen for.

Issue intercepting property in Silverlight application

I am using Ninject as DI container in a Silverlight application. Now I am extending the application to support interception and started integrating DynamicProxy2 extension for Ninject. I am trying to intercept call to properties on a ViewModel and ending up getting following exception:
“Attempt to access the method failed: System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[], System.Reflection.Module, Boolean)”
This exception is thrown when invocation.Proceed() method is called. I tried two implementations of the interceptor and they both fail
public class NotifyPropertyChangedInterceptor: SimpleInterceptor
{
protected override void AfterInvoke(IInvocation invocation)
{
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
public class NotifyPropertyChangedInterceptor: IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
I want to call OnPropertyChanged method on the ViewModel when property value is set.
I am using Attribute based interception.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class NotifyPropertyChangedAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
if(request.Method.Name.StartsWith("set_"))
return request.Context.Kernel.Get<NotifyPropertyChangedInterceptor>();
return null;
}
}
I tested the implementation with a Console Application and it works alright.
I also noted in Console Application as long as I had Ninject.Extensions.Interception.DynamicProxy2.dll in same folder as Ninject.dll I did not have to explicitly load DynamicProxy2Module into the Kernel, where as I had to explicitly load it for Silverlight application as follows:
IKernel kernel = new StandardKernel(new DIModules(), new DynamicProxy2Module());
Could someone please help? Thanks
Reflection can be really tricky in silverlight because of security issues.
Check Gabe's answer for this question, it's the same problem.
The good news is that you can achieve the same functionality you want using dynamic instead of proxies. Just extend your ViewModel from DynamicObject and override the TrySetMember method.
I hope it helps :)

Is it possible to show/hide UserControls within a Silverlight XAP file from JavaScript?

I've created a Silverlight project that produces [something].xap file to package a few silverlight UserControls. I would like to manipulate that .xap file through the use of javascript in the browser to show and hide user controls based upon java script events.
Is it possible to do this?
If so any sample could or links to documentation would be appreciated.
Thanks in advance
Kevin
Here's my solution...not sure if it's the "best-practices" way...comments????
In the App class within my Silverlight application I have the following code:
private Page _page = null;
private void Application_Startup(object sender, StartupEventArgs e)
{
_page = new Page();
this.RootVisual = _page;
HtmlPage.RegisterScriptableObject("App", this);
}
Also to the App class I add a [ScriptableMember] to be called from JavaScript
[ScriptableMember]
public void ShowTeamSearch(Guid ctxId, Guid teamId)
{
_page.ShowTeamSearcher(ctxId, teamId);
}
The Page class is the default one that get's created within the Silverlight Control project, it really doesn't have any UI or logic, it's just used to swap in/out the views.
Login oLogin;
TeamSearcher oSearcher;
public Page()
{
InitializeComponent();
oLogin = new Login();
oSearcher = new TeamSearcher();
oLogin.Visibility = Visibility;
this.LayoutRoot.Children.Add(oLogin);
}
Also a method is added to show/hide the views...this could/will probably get more advanced/robust with animations etc...but this shows the basic idea:
public void ShowTeamSearcher(Guid ctxId, Guid teamId)
{
oSearcher.UserTeamId = teamId;
oSearcher.UserContextId = ctxId;
LayoutRoot.Children.Remove(oLogin);
LayoutRoot.Children.Add(oSearcher);
}
Then to invoke this in the JavaScript after assigning the id of oXaml to the instance of the silverlight host.
var slControl = document.getElementById('oXaml');
slControl.Content.App.ShowTeamSearch(sessionId, teamId);
This seems to work and isn't all that bad of a solution, but there might be something better...thoughts?
Here is a my collections of my links for this subject.
Javascript communication to
Silverlight 2.0
Silverlight
interoperability
Silverlight
and JavaScript Interop Basics

Resources