Microsoft Most Valuable Professional

Chris Pietschmann

An MVP From Wisconsin

Add System Menu Items to WPF Window using Win32 API

A couple weeks ago, I blog how to "Add System Menu Items to a Form using Windows API". Being that WPF has it's differences from Windows Forms, I began to wonder how simple or difficult this would be to do within a WPF application. As it turns out, there are a couple of extra things you need to do, but the code is pretty much the same.

This is something I used to have a code snippet for in VB6, but I haven't needed to do this in a while so I never wrote up an example in .NET. So, here's the simple code necessary to add some custom menu items to your applications System Menu within a WPF application. If you're not familiar, the System Menu is the menu that shows up if you click on the apps icon in the upper left or if you right click the app in the taskbar.

Below is a screenshot of it in action along with the complete source code in C#.

using System;
using System.Windows;
using System.Runtime.InteropServices;
using System.Windows.Interop;

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        #region Win32 API Stuff

        // Define the Win32 API methods we are going to use
        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, Int32 wFlags, Int32 wIDNewItem, string lpNewItem);

        /// Define our Constants we will use
        public const Int32 WM_SYSCOMMAND = 0x112;
        public const Int32 MF_SEPARATOR = 0x800;
        public const Int32 MF_BYPOSITION = 0x400;
        public const Int32 MF_STRING = 0x0;

        #endregion

        // The constants we'll use to identify our custom system menu items
        public const Int32 _SettingsSysMenuID = 1000;
        public const Int32 _AboutSysMenuID = 1001;

        /// <summary>
        /// This is the Win32 Interop Handle for this Window
        /// </summary>
        public IntPtr Handle
        {
            get
            {
                return new WindowInteropHelper(this).Handle;
            }
        }

        public Window1()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }

        private void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            /// Get the Handle for the Forms System Menu
            IntPtr systemMenuHandle = GetSystemMenu(this.Handle, false);

            /// Create our new System Menu items just before the Close menu item
            InsertMenu(systemMenuHandle, 5, MF_BYPOSITION | MF_SEPARATOR, 0, string.Empty); // <-- Add a menu seperator
            InsertMenu(systemMenuHandle, 6, MF_BYPOSITION, _SettingsSysMenuID, "Settings...");
            InsertMenu(systemMenuHandle, 7, MF_BYPOSITION, _AboutSysMenuID, "About...");

            // Attach our WndProc handler to this Window
            HwndSource source = HwndSource.FromHwnd(this.Handle);
            source.AddHook(new HwndSourceHook(WndProc));
        }

        private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // Check if a System Command has been executed
            if (msg == WM_SYSCOMMAND)
            {
                // Execute the appropriate code for the System Menu item that was clicked
                switch (wParam.ToInt32())
                {
                    case _SettingsSysMenuID:
                        MessageBox.Show("\"Settings\" was clicked");
                        handled = true;
                        break;
                    case _AboutSysMenuID:
                        MessageBox.Show("\"About\" was clicked");
                        handled = true;
                        break;
                }
            }

            return IntPtr.Zero;
        }
    }
}

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General | Win32API
Posted by crpietschmann on Thursday, March 27, 2008 4:41 PM
Permalink | Comments (0) | Post RSSRSS comment feed


.NET Community: Learn The Current State Of The Platform Before Deciding On Its Future

There has been some discussion lately in the blogosphere and on DotNetKicks around the subject of "What is wrong with the ASP.NET Community?". There has been alot of discussions goin on, and it has really gotten me thinking.

Before reading on, please read the following two posts in order.

What is wrong with the ASP.NET Community? - by Dan Hounshell

The ASP.NET community's only real problem is education - by Jeff Putz

Now that you've read the above two posts, I'll go on...

What's the Real Problem?

In Dan's post, "What is wrong with the ASP.NET Community?", he goes on to say that the problem is that the ASP.NET community is rather immature for its age, and he gives a pyramid example that explains the community is driven by a select few Community Leaders. These community leaders are people such as: Scott Guthrie (MS Employee), Rob Conery (MS Employee), Phil Haack (MS Employee). I would even say that Scott Hanselman (MS Employee) also falls in to this "Community Leaders" category. Dan also explains that Microsoft needs to pull its hand out of the cookie jar, in order for the community to mature on its own.

In Jeff's post, "The ASP.NET community's only real problem is education", he explains that Dan and the others are asking the wrong question. In fact Jeff thinks the real problem is that people (the community) are asking the wrong kinds of questions. People keep asking, "What's the command for [this]?" and "How do I save a cookie?". They are looking for a quick fix, without an inclination of how to actually perform the task. He explains the reasoning for this is because most of the community comes from a simpler VB6 and Classic ASP background where everything wasn't Object Oriented, and there were alot of quick fixes for everything.

Dan identifies that there is a problem, and Jeff hits the problem on the head:

The .NET development community is under educated.

I'm not saying that Dan was wrong, I only think that he wasn't looking in the correct place to find the real problem. Dan was looking at the select few, the community leaders, thinking they're the ones limiting the real growth of the community. When in fact, the reall problem lies with the majority, the average developer, and the fact that they are just plain under educated about the .NET development plaftworm.

I also think that both Dan and Jeff are looking at things from the wrong angle; the problem isn't just the ASP.NET community, it's the entire .NET development community.

What's the Solution?

The solution to this education problem is plain and simple: The average .NET developer needs to spend a little more time learning the platform.

Here are a couple different areas that I can see need improvement:

  • Get a better understanding of Object Oriented Programming (OOP)
  • Get a better understanding of Event Driven Programming
  • Get a better understanding of what the .NET Framework already provides
  • Get a better understanding of Design Patterns
  • Learn to read/write both C# and VB.NET

I'm sure there are other areas the .NET community needs to focus on, and if you can think of any, please post them in the comments.

Why "Get a better understanding of Object Oriented Programming (OOP)?"

The .NET Framework is completely Object Oriented. Without a good understanding of OOP, you will be lost at sea without a compass.

This reminds me of the following analogy: If you're a Classic ASP/VB6 developer, and you just jump in to writing ASP.NET code without learning anything (or enough) about the environment and platform, then you'll just be writing a Classic ASP/VB6 program in ASP.NET.

Why "Get a better understanding of Event Driven Programming?"

The .NET Framework is very heavy on Event Driven Programming. All three of the Windows Forms, ASP.NET and WPF programming models make use of Event Driven Programming.

Developers that come from VB6 Desktop development will have a basic understanding of Event Driven Programming, but developers from Classic ASP most likely wont.

The same analogy I wrote above for OOP, applies just as relavent to Event Driven Programming.

Why "Get a better understanding of what the .NET Framework already provides?"

There is so much functionality already baked in the .NET Framework that it's impossible for a single developer to fully understand and know how to use it all. This is why I'm saying "Get a better understanding" instead of "Understand it all".

By getting a better understanding of what's already in the framework (best to focus on stuff relavent to your area of expertise, be it ASP.NET, Windows Forms, WPF, WCF, etc.) you will become a much more productive developer. You wont be constantly rewriting code that's already there for the using. For example: The VirtualPathProvider in ASP.NET has alot of usefull path related methods, but most ASP.NET developers aren't familiar with it.

Why "Get a better understanding of Design Patterns?"

You may be wondering why I'm including Design Patterns in this list? Because, Design Patterns are architectural best practices in programming. Much of the code within the .NET Framework itself makes use of many different Design Patterns. Simply put, by learning Design Patterns, you will become a better developer since your code will be more reusable, extensible and easier to read.

Why "Learn to read/write both C# and VB.NET?"

The development community is still very split in the middle as to whether they prefer C# or VB.NET. Because of this, the plethora of code examples on the web aren't written in both. In my experience, I've found it appears that more examples are written in C# than VB.NET.

I'm not saying to necessarily become an expert with the nuances of both languages, but being able to read and write both will definately benefit you in more ways than one. Especially when looking for a new job, some shops want C# developers and others want VB.NET developers, and if you know both then you wont be elliminating job opportunities for now reason.

Where do you find the time to learn all this stuff?

You may be wondering how one would find the time to learn all this stuff in between working and life. Well, every developer spends some time reading blogs, articles and/or books. All you have to do is shift some of your time over to focusing on these specific goals. The more each individual furthers their understanding of the .NET Framework and Development Best Practices (no matter how small the amount), the more the .NET development community will improve as a whole, especially if that individual also participates on forums and/or blogs.

After all, it only takes at least a couple minutes a week.

Conclusion

Now that we've (the community, I'm not crediting myself with figuring this out) figured out what both the problem and solution are; we must act on it and fix the problem.

This is the reason I blog and participate on the various developer forums (ASP.NET Forums, MSDN Forums, Silverlight Forums, etc.). I, just like others, are trying to help the community move forward while I move forward with the community. The "community leaders" that Dan speaks of in his post are just like every other average developer; the only difference is (to quote Scott Hanselman from when I met him at Deeper in .NET 2006) "they speak louder".

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: General
Posted by crpietschmann on Thursday, March 27, 2008 10:51 AM
Permalink | Comments (5) | Post RSSRSS comment feed


LinkedIn Group for the Wisconsin .NET Users Group

Here's a link to the Wisconsin .NET Users Group LinkedIn Group I just created. Anyone can join this group on LinkedIn, and it's a nice way to show your affiliation with the WI .NET Users Group within your LinkedIn profile.

http://www.linkedin.com/e/gis/77233/49CA3D077B3C

Also, heres a link to the Facebook group for the Wisconsin .NET Users Group:

http://www.facebook.com/group.php?gid=2875089211

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: General | WI-INETA
Posted by crpietschmann on Tuesday, March 25, 2008 4:36 PM
Permalink | Comments (1) | Post RSSRSS comment feed


PasswordTextBox for Silverlight 2 Beta 2

The standard TextBox control that is built into Silverlight 2 Beta 2 is a bit lacking and is missing alot of features that we have become accustomed to in a TextBox. One of those features is being able to mask the characters being displayed when its used to accept passwords. Here's a small PasswordTextBox control I built that does just that; it masks the characters from being displayed so you can accept passwords like you're used to.

Update 6/7/2008 - I just tested this with Silverlight 2 Beta 2 and it works just the same as it does with Beta 1. 

Updated 3/17/2008 - I updated this code to support the Delete and Backspace keys, and to maintain caret/cursor position within the box. I also added the PasswordChar property that defines what the masking character is used to hide the password entered.

/// Copyright 2008 Chris Pietschmann (http://pietschsoft.com)
/// This work is licensed under a Creative Commons Attribution 3.0 United States License
/// http://creativecommons.org/licenses/by/3.0/us/
///
/// This is a Password TextBox built for use with Silverlight 2 Beta 1
/// The reason this was built, is because the standard TextBox in
/// Silverlight 2 Beta 1 does not have Password support.
/// Original Link: http://pietschsoft.com/post/2008/03/PasswordTextBox-for-Silverlight-2-Beta-1.aspx
///

using System.Windows.Controls;

namespace SilverlightPasswordTextBox
{
    public partial class PasswordTextBox : TextBox
    {
        public PasswordTextBox()
        {
            this.TextChanged += new TextChangedEventHandler(PasswordTextBox_TextChanged);
            this.KeyDown += new System.Windows.Input.KeyEventHandler(PasswordTextBox_KeyDown);
        }

        #region Event Handlers

        public void PasswordTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (base.Text.Length >= _Text.Length)
                _Text += base.Text.Substring(_Text.Length);
            DisplayMaskedCharacters();
        }

        public void PasswordTextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            int cursorPosition = this.SelectionStart;
            int selectionLength = this.SelectionLength;

            // Handle Delete and Backspace Keys Appropriately
            if (e.Key == System.Windows.Input.Key.Back
                || e.Key == System.Windows.Input.Key.Delete)
            {
                if (cursorPosition < _Text.Length)
                    _Text = _Text.Remove(cursorPosition, (selectionLength > 0 ? selectionLength : 1));
            }
           
            base.Text = _Text;
            this.Select((cursorPosition > _Text.Length ? _Text.Length : cursorPosition), 0);
            DisplayMaskedCharacters();
        }

        #endregion

        #region Private Methods

        private void DisplayMaskedCharacters()
        {
            int cursorPosition = this.SelectionStart;
           
            // This changes the Text property of the base TextBox class to display all Asterisks in the control
            base.Text = new string(_PasswordChar, _Text.Length);

            this.Select((cursorPosition > _Text.Length ? _Text.Length : cursorPosition), 0);
        }

        #endregion

        #region Properties

        private string _Text = string.Empty;
        /// <summary>
        /// The text associated with the control.
        /// </summary>
        public new string Text
        {
            get { return _Text; }
            set
            {
                _Text = value;
                DisplayMaskedCharacters();
            }
        }

        private char _PasswordChar = '*';
        /// <summary>
        /// Indicates the character to display for password input.
        /// </summary>
        public char PasswordChar
        {
            get { return _PasswordChar; }
            set { _PasswordChar = value; }
        }

        #endregion
    }
}

Update 4/2/2008: Here's the above code translated to VB.NET

'' Copyright 2008 Chris Pietschmann (http://pietschsoft.com)
'' This work is licensed under a Creative Commons Attribution 3.0 United States License
'' http://creativecommons.org/licenses/by/3.0/us/
''
'' This is a Password TextBox built for use with Silverlight 2 Beta 1
'' The reason this was built, is because the standard TextBox in
'' Silverlight 2 Beta 1 does not have Password support.
'' Original Link: http://pietschsoft.com/post/2008/03/PasswordTextBox-for-Silverlight-2-Beta-1.aspx
Public Class PasswordTextBox
    Inherits TextBox

    Public Sub PasswordTextBox_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs) Handles Me.TextChanged
        If MyBase.Text.Length >= _Text.Length Then
            _Text += MyBase.Text.Substring(_Text.Length)
        End If
        DisplayMaskedCharacters()
    End Sub

    Public Sub PasswordTextBox_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
        Dim cursorPosition As Integer = Me.SelectionStart
        Dim selectionLength As Integer = Me.SelectionLength

        '' Handle Delete and Backspace Keys Appropriately
        If e.Key = Key.Back Or e.Key = Key.Delete Then
            If cursorPosition < _Text.Length Then
                Dim lengthToRemove As Integer = 1
                If selectionLength > 0 Then lengthToRemove = selectionLength
                _Text = _Text.Remove(cursorPosition, lengthToRemove)
            End If
        End If

        MyBase.Text = _Text
        If cursorPosition > _Text.Length Then
            Me.Select(_Text.Length, 0)
        Else
            Me.Select(cursorPosition, 0)
        End If
        DisplayMaskedCharacters()
    End Sub

    Private Sub DisplayMaskedCharacters()
        Dim cursorPosition As Integer = Me.SelectionStart

        '' This changes the Text property of the base TextBox class to display all Asterisks in the control
        MyBase.Text = New String(_PasswordChar, _Text.Length)

        If cursorPosition > _Text.Length Then
            Me.Select(_Text.Length, 0)
        Else
            Me.Select(cursorPosition, 0)
        End If
    End Sub

    Private _Text As String = String.Empty
    Overloads Property Text() As String
        Get
            Return _Text
        End Get
        Set(ByVal value As String)
            _Text = value
            DisplayMaskedCharacters()
        End Set
    End Property

    Private _PasswordChar As Char = "*"
    Public Property PasswordChar() As Char
        Get
            Return _PasswordChar
        End Get
        Set(ByVal value As Char)
            _PasswordChar = value
        End Set
    End Property

End Class

 

Currently rated 5.0 by 6 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Silverlight
Posted by crpietschmann on Friday, March 14, 2008 8:25 PM
Permalink | Comments (13) | Post RSSRSS comment feed

Working with HTML DOM in Silverlight 2 Beta 1 using the Bridge Pattern

Working with the HTML DOM in Silverlight 2 Beta 1 is rather simple and easy to do. However, to my surprise it's a similar experience to working the the HTML DOM from within JavaScript; you have to know the name of the properties to get/set and you don't have the luxury of compile time checking or intellisense.

Here an example of creating a new DIV element and setting some of it's properties:

HtmlElement myDiv = HtmlPage.Document.CreateElement("div");

// Set the innerHTML property
myDiv.SetProperty("innerHTML", "<strong>Some HTML Content</strong>");

// Set some style properties
myDiv.SetStyleAttribute("border", "solid 1px black");
myDiv.SetStyleAttribute("position", "absolute");
myDiv.SetStyleAttribute("top", "10px");
myDiv.SetStyleAttribute("left", "10px");

// Add the myDiv element to the page
HtmlPage.Document.Body.AppendChild(myDiv);

// Get the innerHTML property
string html = myDiv.GetProperty("innerHTML");

// Get the Position Style attribute
string pos = myDiv.GetStyleAttribute("position");

As you can see from the above example, the HtmlElement object doesn't have any real properties or style attributes, you must work with the helper methods to get/set them. I was a little surprised to see this at first, and I don't know if they plan on adding any properties to the object in the final release or if they are doing this to just make the Silverlight download smaller.

Can We Extend the HtmlElement to Add Property Accessors?

Yes, but not through inheritence. For some reason they decided to make the System.Windows.Browser.HtmlElement class Sealed! So, instead we'll have to use the Bridge Pattern to create a wrapper object that will have all the desired property accessors.

Here's an example of using a class that implements the Bridge Pattern to do the exact same as above:

HtmlElementHelper myDiv = new HtmlElementHelper(HtmlPage.Document.CreateElement("div"));
myDiv.innerHTML = "<strong>Some HTML Content</strong>";
myDiv.Style.Position = "absolute";
myDiv.Style.Border = "solid 1px black";
myDiv.Style.Top = "10px";
myDiv.Style.Left = "10px";
HtmlPage.Document.Body.AppendChild(myDiv.Element);

Not only is the code using the Bridge Pattern easier to read, but now we have the benefit of compile time checking of our DIV elements properties. No need to worry if you misspelled any of the property names anymore.

Full Source Code for the HtmlElementHelper Bridge class:

 public class HtmlElementHelper
    {
        private HtmlElement _elem = null;
        private HtmlElementStyleHelper _styleHelper = null;
       
        public HtmlElementHelper(HtmlElement elem)
        {
            this._elem = elem;
        }

        public HtmlElement Element
        {
            get { return _elem; }
        }

        public object GetProperty(string propertyName)
        {
            return _elem.GetProperty(propertyName);
        }

        public void SetProperty(string propertyName, object value)
        {
            _elem.SetProperty(propertyName, value);
        }
       
        public HtmlElementStyleHelper Style
        {
            get
            {
                if (_styleHelper == null)
                {
                    _styleHelper = new HtmlElementStyleHelper(this._elem);
                }
                return _styleHelper;
            }
        }

        public string innerHTML
        {
            get { return GetProperty("innerHTML") as string; }
            set { this.SetProperty("innerHTML", value); }
        }

        public string innerText
        {
            get { return GetProperty("innerText") as string; }
            set { this.SetProperty("innerText", value); }
        }

        public string className
        {
            get { return GetProperty("className") as string; }
            set { SetProperty("className", value); }
        }

        public string Id
        {
            get { return _elem.Id; }
            set { _elem.Id = value; }
        }
    }

    public class HtmlElementStyleHelper
    {
        private HtmlElement _elem = null;

        public HtmlElementStyleHelper(HtmlElement elem)
        {
            this._elem = elem;
        }

        public string GetAttribute(string name)
        {
            return _elem.GetStyleAttribute(name);
        }

        public void SetAttribute(string name, string value)
        {
            _elem.SetStyleAttribute(name, value);
        }

        public string Position
        {
            get { return GetAttribute("position"); }
            set { SetAttribute("position", value); }
        }

        public string Border
        {
            get { return GetAttribute("border"); }
            set { SetAttribute("border", value); }
        }

        public string Top
        {
            get { return GetAttribute("top"); }
            set { SetAttribute("top", value); }
        }

        public string Left
        {
            get { return GetAttribute("left"); }
            set { SetAttribute("left", value); }
        }

        public string Width
        {
            get { return GetAttribute("width"); }
            set { SetAttribute("width", value); }
        }

        public string Height
        {
            get { return GetAttribute("height"); }
            set { SetAttribute("height", value); }
        }
    }

Conclusion

I have actually never had such a usefull need to use the Bridge Pattern before, and this time it really saves the day. I hope Microsoft adds better support for the different HTML DOM Elements properties and style properties to the Silverlight 2 final release, or at least open up the HtmlElement object for inheritence. If neither, at least we can use the Bridge Pattern to fullfill our needs.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Silverlight
Posted by crpietschmann on Wednesday, March 12, 2008 12:00 AM
Permalink | Comments (3) | Post RSSRSS comment feed

Show a MessageBox in Silverlight 2 Beta 1

Since Silverlight is just a subset of WPF, there are alot of things missing. One missing thing I found is the System.Windows.MessageBox. I'm a little puzzled as to why they would have left this out, but I imagine MessageBox's are handled very differently in different Operating Systems. It's probably a little work to get it working on both Mac and Windows, but I hope it gets into the final release. It's not a major feature, but one that is used quite often when developing desktop applications, so I can see it being used alot in Silverlight applications.

Anyways, here's a small implementation I wrote that wraps up the JavaScript Alert to give us a basic MessageBox to use for now:

public static class MessageBox
{
    public static void Show(string message)
    {
        HtmlPage.Window.Alert(message);
    }
}

Update 4/2/2008: I updated the above example to use the "HtmlPage.Window.Alert" method instead of the Invoke method; better to use the method that's already in the framework.

Also, here's the above code example in VB.NET:

Module MessageBox
    Public Sub Show(ByVal message As String)
        HtmlPage.Window.Alert(message)
    End Sub
End Module

 

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Silverlight
Posted by crpietschmann on Saturday, March 08, 2008 6:13 PM
Permalink | Comments (2) | Post RSSRSS comment feed

MIX'08 Session Recordings Now Available Online

The MIX'08 Session Recordings are now available online. So far, its just the recordings from yesterday, but all the recordings for the entire event should be up by Monday. This is really awesome, you can almost attend the event for free online. Go check it out.

http://sessions.visitmix.com/

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by crpietschmann on Thursday, March 06, 2008 10:42 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Opening Client-Side Files using Silverlight

Silverlight does not have direct access to the local file system for security reasons. However, you can still prompt the user to select a specific file to open using the OpenFileDialog similarly to how you do in .NET. Here's some basic code that demonstrates opening a user specified file using Silverlight 2 Beta 1.

This basic example opens up a user specified file, and displays its contents within a textbox.

Page.xaml file

<UserControl x:Class="SilverlightFileSystemInfo.Page"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="480">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid HorizontalAlignment="Left">
            <TextBox x:Name="txtFile" Width="400" Height="250" AcceptsReturn="True" />   
        </Grid>
        <Grid HorizontalAlignment="Right" VerticalAlignment="Top">
            <Button x:Name="btnSelectFile" Content="Add File" Width="75" Height="30" Click="btnSelectFile_Click"></Button>
        </Grid>
    </Grid>
</UserControl>

Page.xaml.cs file 

using System.Windows;
using System.Windows.Controls;
using System.IO;

namespace SilverlightOpenFileTest
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
        }

        private void btnSelectFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();

            // Show the Open File Dialog
            DialogResult result = fileDialog.ShowDialog();

            // Open the file if OK was clicked in the dialog
            if (result == DialogResult.OK)
            {
                FileDialogFileInfo fi = fileDialog.SelectedFile;
                Stream s = fi.OpenRead();
                StreamReader reader = new StreamReader(s);
                txtFile.Text = reader.ReadToEnd();
            }
        }
    }
}

Now isn't that simple? I wonder if they'll ever add the SaveFileDialog...

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Silverlight
Posted by crpietschmann on Wednesday, March 05, 2008 11:09 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Silverlight: Anatomy of an .XAP file

Silverlight 2 Beta 1 just came out this morning, so I started checking it out immediately. I installed the Silverlight Tools for Visual Studio and noticed that when a Silverlight Application is compiled a .xap file is created that contains the application. But, what exactly is a .xap file, and what exaclty is in there?

What is an .xap file?

A .xap file is basically a compiled Silverlight application. The file is actually a .zip file that contains all the files necessary for the application. Just rename the .xap file to have a .zip extension and then you can open it up to see its contents. Just try it yourself.

What files are contained within the .xap file?

The .xap file contains an application manifest (AppManifest.xaml) file and all the necessary DLL's that are required by the application. The first DLL contained is the compiled version of you application and has the same name of your application. In my test I created an application names "SilverlightApplication1", so the DLL is named "SilverlightApplication1.dll". The rest of the DLL's are the dependancies the application requires.

What is the AppManifest.xaml file?

First lets look at an example AppManifest.xaml file:

[code:xml]

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="SilverlightApplication1" EntryPointType="SilverlightApplication1.App" RuntimeVersion="2.0.30226.2">
  <Deployment.Parts>
    <AssemblyPart x:Name="SilverlightApplication1" Source="SilverlightApplication1.dll" />
    <AssemblyPart x:Name="System.Windows.Controls" Source="System.Windows.Controls.dll" />
    <AssemblyPart x:Name="System.Windows.Controls.Extended" Source="System.Windows.Controls.Extended.dll" />
  </Deployment.Parts>
</Deployment>

[/code]

The first element in the AppManifest.xaml is a Deployment node. This node defines the application and contains child AssemblyPart nodes.

As you can see the AssemblyPart nodes define what assemblies (DLLs) are contained within the .xap file, and give each of them a name.

Now, if you look back up to the top, you'll see the Deployment node has EntryPointAssembly and EntryPointType attributes. The EntryPointAssembly attribute defines which assembly defined below (as a child AssemblyPart node) is the main assembly (DLL) for the application. And, the EntryPointType attribute specifies the Class contained within the assembly (DLL), defined in the EntryPointAssembly attribute, is the main class that will be instantiated to start the application.

The Deployment node also has a RuntimeVersion attribute that defines the version of Silverlight the application is built for.

Conclusion 

There you go, now you have a basic understanding of what an .xap file is. This article was written using Silverlight 2 Beta 1, so things may change in the final release, but I image the basics described here will still remain the same.

I'm sure there are more child nodes and attributes that can be defined within the AppManifest.xaml file, but I have yet to see what they are since, I'm still new to Silverlight 2.0.

Currently rated 4.7 by 6 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Silverlight
Posted by crpietschmann on Wednesday, March 05, 2008 1:24 PM
Permalink | Comments (2) | Post RSSRSS comment feed

MIX'08 - KeyNote Notes of Ray Ozzies talk

I watched the MIX'08 Keynote online this morning, and here are some notes I took. 

Notes from Ray Ozzies talk:

Some investments will be realized this week:

  • Internet Explorer 8
  • Silverlight 2

Advertising on the web is expected to grow from $40 billion to $80 billion over the next few years.

Social networking is growing and will become an integral part of the web just as familiar as Files and Folders are on the desktop.

Web will be used as a hub in using and managing all kinds of devices (Zune, SmartPhones, PCs).

Power of choice will be given to Business/Enterprises that will utilize virtualization to allow a better level of symetry between software and services in the "cloud".

We need to realize a fabric of services (loosely coupled) that range from applications in the cloud to standard desktop or server applications that can easily communicate. RSS and REST are being used in this new fabric that is forming.

Seamless, Rich Applications are being expected to be cross platform. XAML, Silverlight and WPF are going to allow this.

Over the next 5 years, the way we write, maintain and debug code are going to move more into the "cloud".

5 major groups of product offerings:

  • Connected Devices - Connected using the cloud to allow centralized personalization and control. Unified data management using the synchronization of files and data. Web based deployment of Device applications.
  • Connected Entertainment - Same vision of connected devices, you'll only need to register your media license once and share it accross your devices. Devices that can connect/link into social networking more seamlessly.
  • Connected Productivity - Office for PC, Office Mobile for Phone, and Office Live for the Web. Ability to be productive anywhere.
  • Connected Bussiness - Smaller business can take advantage of CRM Live and services that only enterprises had access to previously. Bussines's given the choise to run services (such as Sharepoint and Exchange) locally or in the "cloud".
  • Connected Development - Services and Tools that span seamlessly across devices. XNA, Silverlight and .NET are allowing us to realize this today.

Silverlight was announces last year; this year they are going to deliver on that promise.

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: General
Posted by crpietschmann on Wednesday, March 05, 2008 11:32 AM
Permalink | Comments (0) | Post RSSRSS comment feed

About the author

I'm Chris Pietschmann, go to the About Me page to learn more about me.

Search

Sponsors

Web.Maps.VE - ASP.NET AJAX Virtual Earth Mapping Server Control

Recent comments

Disclaimer


This work is licensed under a Creative Commons Attribution 3.0 United States License, unless explicitly stated otherwise within the posted content.
© Copyright 2004 - 2008 Chris Pietschmann