Update (November 14th 2012): download a code sample that contains this hack.
The problem: You cannot bind to non-public types in LightSwitch.
So you’ve read the article about creating reusable modal screens in LightSwitch (whoa, thanks!), you tried it out (whoa, even more thanks!) and found out it only works in out-of-browser applications (whoa! bummer! My bad, sorry!!)
It took me a while to find some spare time (sorry about that), but I finally got around to digging into this exception (yes, I’m doing this over playing with the new HTML client 🙂). With the feedback from MikeH and Alfonso (thanks guys!), it was easy to diagnose the issue:
- This works in an out-of-browser application.
- This does not work in an “in-browser” application. The stacktrace in the output window reveals:
System.Windows.Data Error: Cannot get ‘[Bla bla]’ value (type '[Bla bla]’) from ‘[more bla]’ (type ‘[something something]’). BindingExpression: Path=’[the path]’ DataItem=’[the data item] (HashCode=[whatever]); target element is ‘My imba user control’ (Name=”); target property is ‘[some prop]’ (type ‘[more fully qualified types in here]’).. System.MethodAccessException: Attempt by method ‘System.Windows.CLRPropertyListener.get_Value()’ to access method ‘[getter on the method]’ failed. at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, UInt32 invocationFlags) at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, UInt32 invocationFlags) [more stacktrace here] at System.Windows.PropertyAccessPathStep.ConnectToPropertyInSource(Boolean isSourceCollectionViewCurrentItem).
I’m including this stack trace so the next guy that runs into this problem can find this post.
Right, so back to analyzing the problem: Bugger. However, this behavior and stack trace seem to indicate there was a problem with the reflection being used in Silverlight bindings, which in turn is more restrictive in “in-browser” applications than it is in out-of-browser applications. Indeed, with a bit of time spent on Bing, it turns out you cannot bind to properties on non-public types in Silverlight. Even if these properties are exposed via a public interfaces.
Possible workarounds are:
- Make your properties / classes public. Say bye-bye to any good coding practices, *sigh*.
- Expose your privates.Well except for the fact this is the first time I explicitly write about my readers privates, I cannot make the internal types public since I do not own the assembly. I mailed Microsoft to add ‘Application1337″, my test application, a trusted assembly from Microsoft.LightSwitch.Client.Internal.dll, the assembly that contains the internal type, but they politely refused.
- Create a public decorator.
Understanding the decorator design pattern.
You can read all about the decorator pattern on wiki, or read my really short version here:
The decorator pattern is where you wrap one class around another. The wrapper (the outer class) implements the same interface as the decorated class (the inner class), so the caller has no idea that there is a wrapper. The wrapper delegates all calls to events, properties or methods, as defined on the interface, to the decorated class, except for those where the decorator chooses to alter the behavior.
Basically, if it looks like a duck, quacks like a duck and walks like a duck, it could be you’re dealing with a duck. However, you aren’t sure. If you ask it to Quack() (IDuck interface), it could be the Duck implementation (decorated class) that quacks, or it could be the farmer (wrapper, aka the decorator) that squeezes a duck hard enough to quack. Some decorator classes are hard-coded, although you can create generic (dynamic proxy) implementations as well.
In our case, we had a problem binding to a non-public type. We can create a decorator for our non-public type, which alters the behavior only by being a public type.
The code sample.
Here’s the decorator for the IScreenView, copy&paste the class to your LightSwitch project if you intend to make the reusable modal screens article work in in-browser applications:
public class PresentationScreenViewDecorator : IScreenView { private IScreenView decorated; public PresentationScreenViewDecorator(IScreenView decorated) { this.decorated = decorated; } public void ActivateUIElement(Microsoft.LightSwitch.IBusinessObject target, Microsoft.LightSwitch.Details.IBusinessProperty targetProperty) { this.decorated.ActivateUIElement(target, targetProperty); } public void BeginModal(IScreenModalDialog dialog) { this.decorated.BeginModal(dialog); } public void CommitUIChanges() { this.decorated.CommitUIChanges(); } public void EndModal(IScreenModalDialog dialog) { this.decorated.EndModal(dialog); } public bool Focus() { return this.decorated.Focus(); } public IScreenModalDialog[] GetActiveModalDialogs() { return this.decorated.GetActiveModalDialogs(); } public bool IsShowingModal { get { return this.decorated.IsShowingModal; } } public event System.EventHandler PreviewShowingModal { add { this.decorated.PreviewShowingModal += value; } remove { this.decorated.PreviewShowingModal -= value; } } public System.Windows.FrameworkElement RootUI { get { return this.decorated.RootUI; } } public IScreenObject Screen { get { return this.decorated.Screen; } } public IEnumerable ShellCommands { get { return this.decorated.ShellCommands; } } public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged { add { this.decorated.PropertyChanged += value; } remove { this.decorated.PropertyChanged -= value; } } public void Dispose() { this.decorated.Dispose(); this.decorated = null; } }
A novice reader should be able to understand how this example works: I’m decorating an instance of IScreenView by delegating all calls on the IScreenView interface to properties, methods and events to the decorated instance.
A professional reader could notice I haven’t successfully succeeded in my encapsulation, I should for example encapsulate the IShellCommands returned by the call to the ShellCommands property. Make me.
Anyways, using this simple trick, you can now update the example from the Reusable Screens article like below:
public MyModalWindow(ModalCall call) { this.call = call; //this.DataContext = this.call.ModalChildView; //Find the line above, and replace with: this.DataContext = new PresentationScreenViewDecorator(this.call.ModalChildView); InitializeComponent(); this.Closing += MyModalWindow_Closing; }
Enjoy, and keep rocking LS!
PS: (insider) Yes, Michael Washington was right and I promise never to do that again. 🙂
PS2: I created a bug about this. Doesn’t seem like a logical equation… public interface + public property = binding should work.
Pingback: Creating reusable modal screens « Jan Van der Haegen's blog
Hi Jan
Thanks for the new code.
Just a note: when I’m trying it, i have to change a little thing:
public event System.EventHandler PreviewShowingModal
{
add
{
this.decorated.PreviewShowingModal += value;
}
remove
{
this.decorated.PreviewShowingModal -= value;
}
}
TO:
public event System.EventHandler PreviewShowingModal
{
add
{
this.decorated.PreviewShowingModal += value;
}
remove
{
this.decorated.PreviewShowingModal -= value;
}
}
and I have to add this to implement the IScreenView interface
event System.EventHandler IScreenView.PreviewShowingModal
{
add { throw new System.NotImplementedException(); }
remove { throw new System.NotImplementedException(); }
}
IEnumerable IScreenView.ShellCommands
{
get { throw new System.NotImplementedException(); }
}
It works perfectly!
Thanks so much
Hey ALfonso!
Don’t know why you had to change that, but glad you got it working!
Keep rocking LS!
Jan
Hi Alfonso
I think I may have a similar error to you.
Do you have a sample of the PresentationScreenViewDecorator with the ‘using’ namespaces please
Many Thanks
Rob
Hey Robert!
I (finally) posted a code sample, it’s about executing a method on the server, but also contains the modal window code: https://janvanderhaegen.wordpress.com/2012/11/14/executing-an-arbitrary-method-or-long-running-process-on-the-lightswitch-server-2-grab-the-code/
Hope you like it!
Keep rocking LS
Works for me too. Thanks Jan!!!
Allright!
Glad you got it working, sorry it took me a while to get a properly working web version…
Keep rocking LS!
Jan
this helped a lot! thanks Jan!
Kivito
Pingback: Windows Azure and Cloud Computing Posts for 8/2/2012+ - Windows Azure Blog
Hi Jan,
This is great post but I have a issue which I need help on it. When I try to close the window I keep getting error at call.ModalHostView.Dispatcher.BeginInvoke(
Error: It is not valid to access this object on the current thread.
Any idea what I may doing wrong.
Ramin
public static void CloseModalWindow(ModalCall call, bool closeHostView)
{
if (call != null && calls.Remove(call))
{
call.CallerView.EndModal(call.ModalHostView);
if (closeHostView)
call.ModalHostView.Dispatcher.BeginInvoke(
() =>
call.ModalHostView.Close()
);
}
}
Me too.
I am getting the same error, have you found a workaround?
Me too, have you solved that?
I fixed this by moving the whole routing inside the BeginInvoke (this is in VB.NET, but I’m sure you can translate):
Public Shared Sub CloseModalWindow(mcall As ModalCall, closeHostView As Boolean)
mcall.ModalHostView.Dispatcher.BeginInvoke(
Sub()
If mcall IsNot Nothing AndAlso calls.Remove(mcall) Then
mcall.CallerView.EndModal(mcall.ModalHostView)
If closeHostView Then
mcall.ModalHostView.Close()
End If
End If
End Sub)
End Sub
DESKTOP games or computer games have greater in
popularity right now, not simply using the younger technology, but in addition
with older people also. There are various online games available,
beginning with the perceptive for the ordinary – your options are absolutely endless.
On the internet role-playing games usually are one of the most a fact
games throughout the complete world. With this particular popularity, a lot of men and women are researching and also striving to learn approaches
to have the entire game as fast as they may;