|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
|
PhillyXAML.org > Blog
|
|
3/4/2010
So I've read about it (and was therefore lucky enough to quickly identify the issue) and knew how to fix it when it happened, but hadn't actually seen it applicable to an application yet.
So here it is. I have a Silverlight application that makes up a component in a web page. Probably saying "Wow"... So far no surprise. The main web application however, which is SharePoint (SL is hosted in a web part), uses jQuery and jQuery UI to display custom help in a modal dialog. When that modal dialog is displayed, the Silverlight plugin instance conceals some of the HTML output on the screen, ie the modal dialog, regardless of Z-Order, and furthermore is not dimmed/disabled as part of the modal dialog being shown.
The image below demonstrates the issue. In this image, and the one that follows, the area designated by the green boundary is the Silverlight application. The area designated in purple is the jQuery modal dialog that is being concealed.
Its also worth noting that the Silverlight application itself remains fully interactive while the "modal" dialog is being shown. This is because the Silverlight application is always set to take highest Z-Order by default, rendering after the HTML has already been rendered to the page, in a sense floating the plugin instance above the page.
I have read and verified that this issue will apply to all HTML-based controls on a page. The majority of issues reported seem to be around dropdowns disappearing behind Silverlight controls, which have their own designated real estate on the page, normally hiding the issue. Not ideally what we want in these situations.
Luckily, the fix is very simple. When we initialize our Silverlight control, we need to set the Windowless attribute equal to true. This will cause the Silverlight application to be rendered in the correct Z-Order with a slight, but virtually unnoticeable performance hit. This will allow our dialog to be rendered after, and therefore on top of our Silverlight control. Additionally, since the control is already rendered to the page, and not floating above the page, so to speak, the browser can handle disabling access to the application by disabling the page, greying it out, etc.
Since the recommended method for adding Silverlight to a page is to use an <object> tag with nested <param> tags, that is what we will cover here. To add our Silverlight instance, we probably have something like this markup generated by Visual Studio by default (with the exception of the initParams parameter shown for example):
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"> <param name="source" value="ClientBin/someXapFile.xap"/> <param name="onError" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="3.0.40624.0" /> <param name="autoUpgrade" value="true" /> <param name="initparams" value="AccessMode=Local,User=John Angelini" /> <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/> </a> </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
All we have to do is pass in another param like so and we should be golden:
<param name="windowless" value="true"/>
The result, Voila! We have a Silverlight application that is baked into the page, displays behind the modal dialog, and most importantly, is no longer interactive, allowing our modal dialog to actually be a modal dialog.
10/30/2009
I recently presented at the Philly.NET CodeCamp. While killing time until it was my turn, I attended a session on Test Driven Development (TDD) using NUnit for creating rich unit testing frameworks using Dependency Injection and Mock Objects, given by Len Smith.
While the topic of TDD is certainly one that warrants further discussion, I want to share a development tool I discovered along the way, as part of Len's demo. So I'm watching, and I see all this cool stuff happening in Visual Studio, that Ive never seen before. I see a bunch of code snippet shortcuts, that I KNOW arent in my copy of Visual Studio... and I see this little icon that keeps popping up, and seemingly, with no clicks or anything, this magical stuff happens and code appears.
By this point, I'm watching in amazement, not at what Len was talking about, but about all these neat little things I was dying to ask him about. I start thinking "Is this a new version of the VS10 bits?" but Ive used those, so Nope... wasnt that.
About 10 minutes in, I heard Len say "something something... ReSharper... something something...." RESHARPER... That was the tender tidbit I was looking for. I made a quick note like a good little geek in my non-iPhone, WINMOBILE Phone to make sure I didnt forget to look it up later.
So I get home and download the fully-functional 30-day trial version and install it. (Trust me if youve made it this far, youre buying this!). I fire up Visual Studio... 2008 not this supercharged new VSNext I thought I was seeing. No. Just my plain old vanilla VS2008... now nicely supercharged!
ReSharper is a product by JetBrains that provides solution-wide error highlighting (and one-click fixes), code refactoring, coding best-practice based code validation, ease of navigation between objects in code and their definitions, as well as numerous other functions... and its extensible!
This tool is a must. Within 15 minutes of using it, I was amazed at some of the errors it found, err... I mean suggestions it made for my code! :) I was also very impressed with some of the advanced refactoring tooling it provides. I was able to easily promote methods and properties to base classes and interfaces.
One of the neatest things I saw was the ability it provides to validate string.Format() calls by looking at the number of arguments, and seeing how many placeholders exist in the format string. Another powerful feature ReSharper provides is suggestions for when methods in your code can be marked as static or if your classes can be sealed, static, etc. You really will learn alot about coding best practices from this tool by the suggestions it provides.
Get all the information at their website... Go there... Now. Run, don't walk. Do not pass GO. Do not collect 200 dollars. Download it. Install it. Use it! You can thank me later. :) 7/24/2009
The second part of this series will cover adding Default and Wait cursors to our application with a simple call to SetWaitCursor or SetDefaultCursor respectively. This is good to use before and after lengthy calls to let the user quickly know the application is doing something. An example might be to call SetWaitCursor, do a DB Query, wait for the results, then call SetDefaultCursor.
We are going to add the following two methods as well as a using statement for System.Windows.Input (for the Cursor object). I have added comments so we can consume this library in other applications and add descriptive meaning to the Intellisense.
/// <summary>
/// Sets the Wait Cursor for the FrameworkElement
/// </summary>
/// <param name="elUI">The FrameworkElement being extended</param>
public static void SetWaitCursor(this FrameworkElement elUI)
{
elUI.Cursor = Cursors.Wait;
}
/// <summary>
/// Sets the Default Cursor for the FrameworkElement
/// </summary>
/// <param name="elUI">The FrameworkElement being extended</param>
public static void SetDefaultCursor(this FrameworkElement elUI)
{
elUI.Cursor = Cursors.Arrow;
}
Now to test the new methods, lets switch back to our code behind file and replace the existing btnTest_Click method code with the following:
private void btnTest_Click(object sender, RoutedEventArgs e)
{
this.SetWaitCursor();
Thread.Sleep(5000);
this.SetDefaultCursor();
}
Run the application and click the bottom button to test the new functionality. The cursor will switch to the Wait cursor, the thread will sleep for 5 seconds, then the cursor will be restored to the Default cursor.
The first part of this series will cover creating our extension method library project in Visual Studio. Additionally, we will create a Test Harness application to test the library as we build it. For an overview on extension methods, read this article.
Lets fire up Visual Studio. First, create a new Class Library using the .NET Framework 3 or 3.5. I named my class library PX.Samples.FrameworkElementExtender. Rename Class1.cs to FrameworkElement.cs. Open the file and replace the default class definition with the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PX.Samples.FrameworkElementExtender
{
public static class FrameworkElementExtender
{
}
}
We want to add a new extension method that we can use to test our library as we go. Its name will be PopTestMessage and it will display the element's Name, Type, ActualWidth and ActualHeight properties in a MessageBox. We will first need to add references to PresentationFramework (for FrameworkElement), PresentationCore (for IInputElement and UIElement) and WindowsBase (for DependencyObject) to our project. Once the references are in our project (Do not add a using statement just yet), enter the following method:
public static void PopTestMessage(this FrameworkElement FE)
{
MessageBox.Show(
string.Format(
"Name: {0}\nType: {1}\nActual Width: {2}\nActualHeight: {3}",
FE.Name,
FE.GetType().ToString(),
FE.ActualWidth,
FE.ActualHeight)
);
}
You should notice we are missing some using statements (like System.Windows for example). Click on the text FrameworkElement and notice the little red smart tag at the bottom right. You can click on the smart tag and in the resultant popup you can choose to add the using statement for the correct namespace. An alternative would be to click somewhere in the text and use Shift-Alt-F10 to pull up the popup menu. I dont like to touch the mouse when Im coding so this works nicely.
However you choose to do it, add a using statement for System.Windows. This will give us access to our MessageBox object and our FrameworkElement object we wish to extend. Our library is now set up for development and we have a complete method to use for testing. Build the project to make sure you dont have any compiling errors.
The next step is going to be to create a Test Harness application to use for testing our library as we build it. Lets create a new WPF project. Name the project TestHarness and choose the same framework you chose for the library (3.0 or 3.5). Set the test harness as the startup project by selecting it in Solution Explorer, right-clicking and choosing Set as Startup Project.
Rename Window1.xaml to winMain.xaml. In the code-behind file rename the class MainWindow and use the refactoring feature (under the smart tag) to rename the class. In App.xaml set the StartupUri to winMain.xaml. In winMain.xaml change the Window's Title to Test Harness and its Width and Height to 800 and 600 respectively. Press F5 or Ctrl-F5 to run the application.
In winMain.xaml, lets add some controls to use to test our method against. Since Control inherits from FrameworkElement, this will give us a valid test. First lets change our root Grid control to a StackPanel so our layout can stay nice and simple. Modify the file to look like the following:
<Window
x:Class="TestHarness.winMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test Harness"
Height="600"
Width="800">
<StackPanel>
<Button
x:Name="btnSample">Test Button 1</Button>
<ComboBox
x:Name="ddlSample"/>
<TextBlock
x:Name="txtSample"
Text="Sample Text Block"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="12"/>
<Rectangle
x:Name="rectSample"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="Red"
Width="600"
Height="400"/>
<Button
x:Name="btnTest"
Margin="12">Click This Button</Button>
</StackPanel>
</Window>
Now lets add a click handler to the bottom button, which we will use for testing our PopTestMessage method. In the designer double-click the bottom Button (btnTest). This will add our handler for us.
The next thing we need to do is add a reference to our library project. Once we have the library referenced, we can simply add a using statement to any file containing code where we wish to use the extension methods. Add the using statement for our library (PX.Samples.FrameworkElementExtender).
Enter in the code for the btnTest_Click method:
private void btnTest_Click(object sender, RoutedEventArgs e)
{
stackMain.PopTestMessage();
btnSample.PopTestMessage();
ddlSample.PopTestMessage();
rectSample.PopTestMessage();
btnTest.PopTestMessage();
}
Run the application and click the bottom button. You should see the method fire for each control in our stack. 7/19/2009When I was writing the article about saving WPF Application screens or controls as images, I started thinking "This would be a great time to write an article about extending the FrameworkElement class to enhance our User Interfaces." Under this premise, we can create a couple simple Extension Methods that can really enhance some of our UIs. The upcoming series of articles will cover developing a library of extension methods we can use to enrich our user experiences with just a little code.
The series breakdown is as follows:
Creating and Consuming our Library - In this article we are going to set up our library project, discuss the structure of the final library, and create our class container. We are also going to discuss how we will use this library in our projects.
Show Default and Wait Cursors - These two extension methods will allow us to very quickly set Wait and Arrow cursors on any control. This allows us to do something like: Set the wait cursor, do some operation, show default cursor.
Animating Fades on User Interface Elements - In this article we will create an overloaded method that will allow us to fade a control to a specific opacity, as well as give us the ability to fade In or Out. A scenario for this might be to fade a window out, open a dialog, and after the dialog call, fade the window back in. This is a scenario we see on the Web all the time. You visit a page, click Login, the window disables and fades, a new window opens, we log in, the login window closes, and the parent window fades back in.
Save a Window or control as an Image - Expanding on the previous article about how to save a window or control as an image, I decided to bake this functionality into the FrameworkElement class itself with a couple of cool overloads.
| Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /blog/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /blog/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
|
|
|
|