OpenLightGroup Blog

rss

Blogs from OpenLightGroup.net


Silverlight Open File Dialog Behavior (MVVM)

image

Live example: [at this link]

This Behavior will allow you to open a Silverlight File Dialog.

 

Here is your View Model:

using System;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.IO;
 
namespace SilvelightViewModelOpenFileDialog
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public MainPageModel()
        {
 
        }
 
        // Operations
        private void SetImage()
        {
            using (Stream stream = SelectedFileProperty.OpenRead())
            {
                BitmapImage image = new BitmapImage();
                image.SetSource(stream);
                SelectedImageProperty = image;
            }
        }
 
        #region SelectedFileProperty
        private FileInfo _SelectedFileProperty;
        public FileInfo SelectedFileProperty
        {
            get
            {
                return this._SelectedFileProperty;
            }
            set
            {
                if (SelectedFileProperty == value)
                {
                    return;
                }
                _SelectedFileProperty = value;
                this.NotifyPropertyChanged("SelectedFileProperty");
                SetImage();
            }
        }
        #endregion
 
        #region SelectedImageProperty
        private BitmapSource _SelectedImageProperty;
        public BitmapSource SelectedImageProperty
        {
            get
            {
                return this._SelectedImageProperty;
            }
            set
            {
                if (SelectedImageProperty == value)
                {
                    return;
                }
 
                _SelectedImageProperty = value;
                this.NotifyPropertyChanged("SelectedImageProperty");
            }
        }
        #endregion
 
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
 
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

 

Here is your UI:

image

Basically just put a Button on the page, and an Image control in a ScrollViewer.

image

Drop an OpenFileDialogBox Behavior on the Button.

image

Click Advanced options next to FileDialogDialogResultCommand.

image

Bind to the SelectedFileProperty and set Binding direction to TwoWay, and click OK.

image

In the Image Control, Click Advanced options next to Source.

image

Bind to the SelectedImageProperty and click OK.

The Behavior

image

To use the Behavior in your own projects, you need only to copy the OpenDialogbehavior.cs file.

Here is the full code for the Behavior:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace OpenLightGroupBehaviors
{
    [System.ComponentModel.Description("Launches a Open File Dialog Box on Event Trigger")]
    public class OpenFileDialogBoxBehavior : TargetedTriggerAction<Button>
    {
        #region FileDialogDialogResultCommandProperty
        public static readonly DependencyProperty FileDialogDialogResultCommandProperty =
            DependencyProperty.Register("FileDialogDialogResultCommandProperty",
            typeof(object), typeof(OpenFileDialogBoxBehavior), null);
        public object FileDialogDialogResultCommand
        {
            get
            {
                return (object)base.GetValue(FileDialogDialogResultCommandProperty);
            }
            set
            {
                base.SetValue(FileDialogDialogResultCommandProperty, value);
            }
        }
        #endregion
        #region DialogFilterProperty
        public static readonly DependencyProperty DialogFilterProperty =
           DependencyProperty.Register("DialogFilter", typeof(string),
           typeof(OpenFileDialogBoxBehavior), null);
        public string DialogFilter
        {
            get
            {
                if (base.GetValue(DialogFilterProperty) == null)
                {
                    return "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg|"
                + "PNG Files (*.png)|*.png|All Files (*.*)|*.*";
                }
                else
                {
                    return (string)base.GetValue(DialogFilterProperty);
                }
            }
            set
            {
                base.SetValue(DialogFilterProperty, value);
            }
        }
        #endregion
        #region Invoke
        //Shows OpenFileDialog on event trigger you set in designer
        protected override void Invoke(object parameter)
        {
            OpenFileDialog objOpenFileDialog = new OpenFileDialog();
            objOpenFileDialog.Filter = DialogFilter;
            objOpenFileDialog.ShowDialog();
            FileDialogDialogResultCommand = objOpenFileDialog.File;
        }
        #endregion
    }
}

 

You can download the code here:
http://silverlight.adefwebserver.com/files/SilvelightViewModelOpenFileDialog.zip





Comments are closed.
Showing 20 Comments
Avatar  Jerry Lee 5 years ago

The xaml does not seem to show up on this site so here it the link to what the xaml should look like for the listbox:&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://stackoverflow.com/questions/8368201/load-images-to-listbox-through-dialog-trouble-with-binding&quot; rel=&quot;nofollow&quot;&gt;stackoverflow.com/questions/8368201/load-images-to-listbox-through-dialog-trouble-with-binding&lt;/a&gt;

Avatar  Jerry Lee 5 years ago

One last thing too. I did not have to use the DelegateCommanding.cs file in my solution. We are doing some custom commanding and it was not required for me. I did go back and comment out the code in the DelegateCommanding.cs file and cleaned the solution and rebuilt it and ran. The solution ran fine without this code. Someone might want to verify but I did not need it. Again Great piece of work!!

Avatar  Jerry Lee 5 years ago

Michael, great job in this blog!! It is a working model. I was able to modify it as needed. I'd like to add my two cents to help this blog be more completed and expand to multiple images:&lt;br /&gt;&lt;br /&gt;In the OpenDialogBehavior.cs file I modified the Invoke method to handle multiple image files.&lt;br /&gt;&lt;br /&gt;Was:&lt;br /&gt; protected override void Invoke(object parameter)&lt;br /&gt; {&lt;br /&gt; OpenFileDialog objOpenFileDialog = new OpenFileDialog();&lt;br /&gt; objOpenFileDialog.Filter = DialogFilter;&lt;br /&gt; objOpenFileDialog.ShowDialog();&lt;br /&gt; FileDialogDialogResultCommand = objOpenFileDialog.File;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;Now:&lt;br /&gt; protected override void Invoke(object parameter)&lt;br /&gt; {&lt;br /&gt; OpenFileDialog objOpenFileDialog = new OpenFileDialog();&lt;br /&gt; objOpenFileDialog.Filter = DialogFilter;&lt;br /&gt; objOpenFileDialog.Multiselect = true;&lt;br /&gt; objOpenFileDialog.ShowDialog();&lt;br /&gt; FileDialogDialogResultCommand = objOpenFileDialog.Files as FileInfo<>;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;I had to modified the following in OpenDialogBehavior.cs from object type to FileInfo<> array:&lt;br /&gt;&lt;br /&gt;Now:&lt;br /&gt;public static readonly DependencyProperty FileDialogDialogResultCommandProperty =&lt;br /&gt; DependencyProperty.Register(&quot;FileDialogDialogResultCommandProperty&quot;,&lt;br /&gt; typeof(FileInfo<>), typeof(OpenFileDialogBoxBehavior), null);&lt;br /&gt;&lt;br /&gt;public FileInfo<> FileDialogDialogResultCommand&lt;br /&gt; {&lt;br /&gt; get&lt;br /&gt; {&lt;br /&gt; return (FileInfo<>)base.GetValue(FileDialogDialogResultCommandProperty);&lt;br /&gt; }&lt;br /&gt; set&lt;br /&gt; {&lt;br /&gt; base.SetValue(FileDialogDialogResultCommandProperty, value);&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;The sample does work with a single image file, however, I needed to be able to load multiple files into a listbox. Here is the xaml:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note that the SelectedImages is bound to the list box item source. This property below shows how to load the images:&lt;br /&gt;&lt;br /&gt;private void SetImages()&lt;br /&gt;{&lt;br /&gt; SelectedImages = new ObservableCollection();&lt;br /&gt; foreach (FileInfo fi in SelectedFiles)&lt;br /&gt; {&lt;br /&gt; using (Stream stream = fi.OpenRead())&lt;br /&gt; {&lt;br /&gt; BitmapImage image = new BitmapImage();&lt;br /&gt; image.SetSource(stream);&lt;br /&gt; SelectedImages.Add(image);&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;I hope this helps!!

Avatar  admin account 5 years ago

@Jerry Lee - (1) Yes (2) Yes (3) could be but I have no examples (4) see: &lt;a href=&quot;http://silverlight.adefwebserver.com/&quot; rel=&quot;nofollow&quot;&gt;silverlight.adefwebserver.com/&lt;/a&gt; for more examples

Avatar  Jerry Lee 5 years ago

I know this article is older but I'm trying to make it work with an in house mvvm framework. I had the basics working I did not actually load an image to the image control because i had previously created my xaml to load the list of images into a listbox. So for a few questions:&lt;br /&gt;&lt;br /&gt;1] Is this still the best way to open a file dialog box?&lt;br /&gt;&lt;br /&gt;2] Is the DelegateCommand.cs file in the solution actually used? If so what is it being used for in this solution?&lt;br /&gt;&lt;br /&gt;3] I modified the behavior's invoke method to be able to select multiple files. No Problem.&lt;br /&gt;&lt;br /&gt;4] So I actually have two buttons one to select one file and one to select multiple files (images). Both buttons open the file dialog box and now I can select one or more files with both buttons. However, when I have objOpenFileDialog.File set to FileDialogResultCommand object the SelectedFileProperty property set is called. If I click on the button that is using a property called SelectedFilesProperty then the property set is never called. Then if I change the objOpenFileDialog.File to objOpenFileDialog.Files never property set is called.&lt;br /&gt;&lt;br /&gt;Nice Article but you should have added some of the xaml to make the article clear. I had to download the project to actually see the xaml.&lt;br /&gt;&lt;br /&gt;thanks!! jerry

Avatar  Leon 6 years ago

very good! appreciate it !!!

Avatar  Ankur Anand 6 years ago

What an elegant solution. Thank you.

Avatar  Jimmy Dickinson 7 years ago

Very helpful

Avatar  MM 7 years ago

I integrated your code (i.e. single .cs file) but _still_ get same security error when trying to open an local file via OpenFileDialog box, from any folder location. My understanding was that this solution was a work-around for not having to create an 'out-of-browser' Silverlight 4 app. Note that if I run your full C# app, I &quot;CAN&quot; load local photos/images just fine. Did I miss something? Specific error encountered is:&lt;br&gt;&lt;br&gt;File operation not permitted. Access to path 'C:\Documents and Settings\mm\My Documents\mytestFiles\test-3.xml' is denied.&lt;br&gt;&lt;br&gt; at System.IO.FileSecurityState.EnsureState()&lt;br&gt; at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)&lt;br&gt; at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)&lt;br&gt; at System.IO.FileInfo.Open(FileMode mode)&lt;br&gt; at OpenLightGroupBehaviors.OpenFileDialogBoxBehavior.Invoke(Object parameter)&lt;br&gt; at System.Windows.Interactivity.TriggerBase.InvokeActions(Object parameter)&lt;br&gt; at System.Windows.Interactivity.EventTriggerBase.OnEvent(EventArgs eventArgs)&lt;br&gt; at System.Windows.Interactivity.EventTriggerBase.OnEventImpl(Object sender, EventArgs eventArgs)&lt;br&gt; at System.Windows.Controls.Primitives.ButtonBase.OnClick()&lt;br&gt; at System.Windows.Controls.Button.OnClick()&lt;br&gt; at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)&lt;br&gt; at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)&lt;br&gt; at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)&lt;br&gt;&lt;br&gt;Appreciate the help!

Avatar  LarsM 7 years ago

Cool approach, well done!&lt;br&gt;&lt;br&gt;A similar Behaviour for Save File Dialog will also be very useful :-)&lt;br&gt;&lt;br&gt;LarsM

Avatar  MM 7 years ago

OK, I'll investigate that. Thanks again.

Avatar  Michael Washington 7 years ago

@MM - You can "request" more storage space from the user. I have no examples but you can Google it.

Avatar  MM 7 years ago

Hi again, and thanks for quick response.&lt;br&gt;&lt;br&gt;Yes, but I already had working OpenFileDialog code in my SL4 C# project. I thought you figured out a way to get around the 'out-of-browser' security restriction. But, thinking about it now, obviously I was incorrect to think this. I planned for my browser app to support for local file saving (which work via SaveFileDialog w/o any security restrictions) _and_ the re-opening of such files back into the app. &lt;br&gt;&lt;br&gt;Is my only option really to go the server storage path? SL4's temporary storage support (limited to only up to 1MB total file capacity) just won't do it -- and neither will the out-of-browser option because it will raise flags to customer IT folks re: network security.&lt;br&gt;&lt;br&gt;Thanks for continuing this dialog (pun intended).&lt;br&gt;Mark

Avatar  Michael Washington 7 years ago

@MM - My sample works for you right? The code must be triggered by a direct user interaction. The code does not (cannot) get around any security restrictions, it only eliminates the need to use code behind.

Avatar  MawashiKid 7 years ago

@MawashiKid - Thanks! However, no other WP7 planned for now.

Avatar  MawashiKid 7 years ago

I know it may sound a bit redundant ...&lt;br&gt;but what the heck... I'll say it again&lt;br&gt;USEFUL, CONCISE &amp; VERY WELL EXPLAINED :)&lt;br&gt;&lt;br&gt;BTW Do you have any future WP7 Beta projects in mind like the MVVM Video Player... ;)&lt;br&gt;&lt;br&gt;Thank's for sharing your expertise. It's very appreciated

Avatar  hattar 7 years ago

Nevermind :) Turns out I somehow had an extra OpenFileDialogBoxBehavior creep into my xaml. Works great, Thanks!

Avatar  hattar 7 years ago

I get an error message stating "Dialogs must be user-initiated." in the "Invoke" method of the Behavior. Am I doing something wrong?

Avatar  Michael Washington 7 years ago

@Denis - Thanks for the comment. It is appreciated. It's the only 'payment' I get :)

Avatar  Denis 7 years ago

Thank you.