Loading Images from the Local machine in Silverlight 3.0

Here I am focusing on two items in Silverlight. First, how to load an image from the local machine to a Image control. Second, show a context menu control to show a OpenFileDialog and select an image locally.

Opening a context menu kind of control code, got from a different site, but missed the link. Once I get that back I will add that in the reference. It has two classes which basically try to attach a event "oncontextmenu". These classes have some cool stuff to make this happen.

This is the output of this application. You can right click on the Rectangle control and select Load Image from the context like menu. This demo just focused on the context menu and loading local image, you may see different behavior for the Context Menu, on the entire page, because the context menu event is get handled in the silverlight application.

Get Microsoft Silverlight

This is how we simulate, the context menu. We created a Popup control in Xaml.

<Popup x:Name="menu">
            <StackPanel>
                <Button x:Name="btnOpenFileDialog" Content="Load Image" ></Button>
                <Button x:Name="btnSayHello" Content="SayHello" ></Button>
            </StackPanel>
        </Popup>

This is the full Xaml Code.

<UserControl x:Class="OpenLocalImageDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="Gray">
        
        <Rectangle x:Name="myRect" 
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Width="300"
                   Height="200"
                   Fill="DarkGray"/>
        <Image x:Name="myImage" Width="300" Height="200"/>
        <Popup x:Name="menu">
            <StackPanel>
                <Button x:Name="btnOpenFileDialog" Content="Load Image" ></Button>
                <Button x:Name="btnSayHello" Content="SayHello" ></Button>
            </StackPanel>
        </Popup>
    </Grid>
</UserControl>

I hope the code is straight forward.

Full C# code

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Browser;
using System.IO;
using System.Windows.Media.Imaging;

namespace OpenLocalImageDemo
{
    public partial class MainPage : UserControl
    {
        private ContextMenuCatcher cm;
        public MainPage()
        {
            InitializeComponent();
            cm = new ContextMenuCatcher(myRect);
            menu.IsOpen = false;
            btnOpenFileDialog.Click += 
                new RoutedEventHandler(btnOpenFileDialog_Click);
            cm.RightClick += 
                new ContextMenuCatcher.RightClickEventHandler(cm_RightClick);
            menu.MouseLeave += 
                new MouseEventHandler(menu_MouseLeave);
            btnSayHello.Click += 
                new RoutedEventHandler(btnSayHello_Click);
        }

        void btnSayHello_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("This is Hello MessageBox");
            menu.IsOpen = false;    
        }

        void menu_MouseLeave(object sender, MouseEventArgs e)
        {
            menu.IsOpen = false;    
        }

        void cm_RightClick(object sender, RightClickEventArgs e)
        {
            menu.HorizontalOffset = e.AbsolutePoint.X;
            menu.VerticalOffset = e.AbsolutePoint.Y;
            menu.IsOpen = true;
        }

        void btnOpenFileDialog_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg";
            ofd.FilterIndex = 1;

            if ((bool)ofd.ShowDialog())
            {
                Stream stream = ofd.File.OpenRead();
                BitmapImage bi = new BitmapImage();
                bi.SetSource(stream);
                myImage.Source = bi;
                stream.Close();

            }
            else
            {
                //user clicked cancel
            }

            menu.IsOpen = false;    
        }
    }

    public class ContextMenuCatcher
    {
        public event RightClickEventHandler RightClick;
        public delegate void RightClickEventHandler
            (object sender, RightClickEventArgs e);
        UIElement ctrl;

        public ContextMenuCatcher(UIElement c)
        {
            ctrl = c;

            HtmlPage.Document.AttachEvent("oncontextmenu", OnContextMenu);
        }

        public ContextMenuCatcher()
        {
            HtmlPage.Document.AttachEvent("oncontextmenu", OnContextMenu);
        }
        private void OnContextMenu(object sender, HtmlEventArgs e)
        {
            Point pt = new Point(e.OffsetX, e.OffsetY);
            e.PreventDefault();
            e.StopPropagation();
            if (RightClick != null)
            {
                RightClick(this, new RightClickEventArgs(ctrl, pt));
            }
        }

    }

    public class RightClickEventArgs
    {

        UIElement m_Source;
        public UIElement Source
        {
            get { return m_Source; }
            set { m_Source = value; }
        }

        Point m_RelativePoint;
        public Point RelativePoint
        {
            get { return m_RelativePoint; }
            set { m_RelativePoint = value; }
        }

        Point m_AbsolutePoint;
        public Point AbsolutePoint
        {
            get { return m_AbsolutePoint; }
            set { m_AbsolutePoint = value; }
        }

        internal RightClickEventArgs(UIElement source, Point absolutePoint)
        {
            this.Source = source;
            this.AbsolutePoint = absolutePoint;
            this.RelativePoint = GetPosition(source);
        }

        public Point GetPosition(UIElement relativeTo)
        {
            GeneralTransform transform = Application.Current.RootVisual.
                                          TransformToVisual(relativeTo);
            return transform.Transform(AbsolutePoint);
        }
    }


}

One last thing to make this application work is to set the Windowless property of the asp:Silverlight control as "true". This is how it looks in my application.

     <asp:Silverlight ID="Silverlight1" runat="server" 
            Source="~/ClientBin/OpenLocalImageDemo.xap" 
            MinimumVersion="3.0.40307.0" 
            Width="100%" Height="100%" 
            Windowless="true"/>

Reference Articles