background image
  logo  
Icon

TagBox 1.0.1

Tue Apr 26th 2011 by Brett
Uptake on TagBox has been great. Thank you everyone for all the feedback and interest. Attached with this post is an updated release which addresses the following bug:

Pressing ENTER repeatedly after selecting a match add a duplicative item for each keypress.

Replacing your previous TagBox assembly with this one will correct the issue.

2 Comments     follow

I wonder when we will have a Silverlight version 5?
Thanks!
posted by rodolphosa on Fri Dec 16th 2011 at 11:19 AM
Is there a WPF version of the TagBox available?
posted by smlyttle78 on Thu Mar 22th 2012 at 9:26 PM
Login to post comments
Icon

Sterling Database

Tue Feb 15th 2011 by Brett
I haven't had a chance to use this in any of my projects yet, but certainly will at the next opportunity. Having written object persistence tools similar to what Jeremy speaks about Sterling would be a real timesaver while adding significant capabilities.

Sterling is an object oriented database written for Silverlight to be used to persist objects to Isolated Storage. It works equally well against SL4 or WP7 Silverlight. The data can be configured to store indexed fields with each persisted object so that querying against large sets of records is fast. It utilizes binary serialization to achieve relatively compact storage.

www.sterlingdatabase.com

0 Comments     follow

Login to post comments
Icon

INPC - ILWeaving to reduce code bloat

Fri Dec 17th 2010 by Brett
Ran into a really nice utility that helps reduce code bloat in situations where you want to implement INotifyProperty changed on simple properties. It injects MSIL during compile to turn from:

    public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string GivenNames { get; set; }
        public string FamilyName { get; set; }
        public string FullName { get { return string.Format("{0} {1}", GivenNames, FamilyName); } }
    }
...to this...
    public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private string givenNames;
        public string GivenNames
        {
            get { return givenNames; }
            set
            {
                if (value != givenNames)
                {
                    givenNames = value;
                    OnPropertyChanged("GivenNames");
                    OnPropertyChanged("FullName");
                }
            }
        }

        private string familyName;
        public string FamilyName
        {
            get
            { return familyName; }
            set
            {
                if (value != familyName)
                {
                    familyName = value;
                    OnPropertyChanged("FamilyName");
                    OnPropertyChanged("FullName");
                }
            }
        }

        public string FullName
        {
            get
            {
                return string.Format("{0} {1}", GivenNames, FamilyName);
            }
        }

        public void OnPropertyChanged(string propertyName)
        {
            var propertyChanged = PropertyChanged;
            if (propertyChanged != null) { propertyChanged(this, new PropertyChangedEventArgs(propertyName)); }
        }
    }
This project handles the weaving for you and is debugging friendly. http://code.google.com/p/notifypropertyweaver/

0 Comments     follow

Login to post comments
Icon

VMCollectionWrapper - Synchronize a Model collection with a ViewModel collection

Tue Sep 21th 2010 by Brett
There has been a lot of debate around what to do with collections of Model objects live under a ViewModel. Consider the situation where a Person has a collection of Nicknames and you have created a PersonViewModel. The debate centers around whether you should expose the Nicknames to binding directly, or if you should create a collection of NicknameViewModels to which binding should occur.

I confess to doing both. In some cases my needs were so simple (perhaps I just needed to display the nicknames) that I would just create a simple property in my ViewModel to expose the nicknames (e.g. public IEnumerable { get { return Model.Nicknames;}}). In 20 seconds I have what I need. Unfortunately this has always left a bad taste in my mouth, and inevitably I end up refactoring them to ViewModels because I need to add some minor functionality I cannot accomplish through data binding alone.

In doing this over-and-over again I found myself:
  1. Creating a new ViewModel that wrapped the Model - easy enough - esp. if I only care about a few properties
  2. Creating a colleciton to hold the ViewModels and populating it from the Models
  3. In cases where I cared about observing changes to this collection in the model - writing code to syncronize the collections. For example adding a Nickname and committing it to the model would require a change to both collections.


Obviously you cannot eliminate #1, but in many cases #2 and #3 where extremely repetitive. I decided to author a collection that would handle this and thus VMCollectionWrapper was born. VMCollectionWrapper can be used in your ViewModel as follows:
public class PersonViewModel : ViewModelBase
{
     public PersonViewModel(Person p)
     {
          //create and populate the VM Collection.  VMCollectionWrapper is observable
          Nicknames = new VMCollectionWrapper<PersonViewModel, Person>(p.NickNames);
     }

     public VMCollectionWrapper<PersonViewModel, Person> Nicknames { get; set; }
}
The code for VMCollectionWrapper looks like this:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace theSilverMethod.MvvM
{
    /// <summary>
    /// Wraps a collection of models with viewmodels.  The underlying collection is updated automatically when 
    /// this collection is changed.  
    /// </summary>
    /// <typeparam name="T">The ViewModel type.  Must implment IViewModelModelProp"/></typeparam>
    /// <typeparam name="U">The model type</typeparam>
    public class VMCollectionWrapper<T,U> : ObservableCollection<T>
        where T : IViewModelModelProp<U>, new()
    {
        private bool _ignoreChanges;
        private IList<U> _wrappedCollection;
        
        public VMCollectionWrapper(IList<U> wrappedModelCollection)
        {
            this.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(VMCollectionWrapper_CollectionChanged);
            _wrappedCollection = wrappedModelCollection;
            if (_wrappedCollection is INotifyCollectionChanged)
            {
                INotifyCollectionChanged childWatch = _wrappedCollection as INotifyCollectionChanged;
                childWatch.CollectionChanged += new NotifyCollectionChangedEventHandler(wrappedCollection_CollectionChanged);
            }
            _ignoreChanges = true;
            foreach (U model in _wrappedCollection) this.Add(new T() { Model = model });
            _ignoreChanges = false;
        }

        /// <summary>
        /// Synchronizes chages from the Models collection to the ViewModels collection
        /// </summary>
        void wrappedCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_ignoreChanges)
                return;
            _ignoreChanges = true;
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
            {
                this.Clear();
                foreach (U model in _wrappedCollection)
                    this.Add(new T() { Model = model });
            }
            else
            {
                var toRemove = new List<T>();
                if (e.OldItems != null && e.OldItems.Count > 0)
                    foreach (U model in e.OldItems)
                        foreach (T viewModel in this)
                            if (viewModel.Model.Equals(model))
                                toRemove.Add(viewModel);
                foreach (T viewModel in toRemove)
                    this.Remove(viewModel);

                if (e.NewItems != null && e.NewItems.Count > 0)
                    foreach (U model in e.NewItems)
                        this.Add(new T() { Model = model });
            }
            _ignoreChanges = false;
        }

        
        /// <summary>
        /// Synchronizes changes from the ViewModels collection to the Models colleciton
        /// </summary>
        void VMCollectionWrapper_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (_ignoreChanges)
                return;

            _ignoreChanges = true;

            // If a reset, then e.OldItems is empty. Just clear and reload.
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
            {
                _wrappedCollection.Clear();

                foreach (T viewModel in this)
                    _wrappedCollection.Add(viewModel.Model);
            }
            else
            {
                // Remove items from the models collection
                var toRemove = new List<U>();

                if (null != e.OldItems && e.OldItems.Count > 0)
                    foreach (T viewModel in e.OldItems)
                        foreach (U model in _wrappedCollection)
                            if (viewModel.Model.Equals(model))
                                toRemove.Add(model);

                foreach (U model in toRemove)
                    _wrappedCollection.Remove(model);

                // Add new viewmodel items to the models collection
                if (null != e.NewItems && e.NewItems.Count > 0)
                    foreach (T viewModel in e.NewItems)
                        _wrappedCollection.Add(viewModel.Model);
            }

            _ignoreChanges = false;

        }

        

    }

   
    public interface IViewModelModelProp <T>
    {
        T Model { get; set; }
    }
}

You will notice that the ViewModel you are using needs to implement IViewModelModelProp which requires that the ViewModel has a property called Model that is correctly typed. This is necessary for syncronization of the collections because we need a way to determine which ViewModels belong to which Views.

Ultimately this doesn't work for every situation, but for the ones it does it sure saves a lot of coding.

Unit tests are here.

2 Comments     follow

Hello, nice article.
I implemented some time ago an article about "Using MVVM to provide undo/redo" that used something similar.
In my version all modifications to the WrapperCollention where converted to commands (for the Undo thing) and send to the wrapped list. The WrapperColletion was actualized using NotifyCollectionChanged. This avoids using _ignoreChanges but maybe is more complex.
My collention also implemented

public interface MirrorCollectionConversor
{
V GetViewItem(D modelItem, int index);
D GetModelItem(V viewItem, int index);
}

to convert between ViewItems a Model items, but maybe your IViewModelModelProp is simpler.
link: http://blog.notifychanged.com/2009/01/30/viewmodelling-lists
posted by danice on Wed Sep 22th 2010 at 3:38 PM
Thanks! Thats funny because I went back and forth several times about where to put the Interface for extracting the model out of the ViewModel. In the actual project I was working on when I authored VMCollectionWrapper I already had a property on my ViewModel called Model so I went that way as it was less code.

In thinking about responsibilities of the classes I think your decision was probably more "responsible" as the VMCollectionWrapper would be less dependent on the implementation of the ViewModel.
posted by Brett on Thu Sep 23th 2010 at 3:28 PM
Login to post comments
Icon

In Defense of Portrait Mode

Tue May 11th 2010 by Brett
For years I wondered about the utility of running monitors in portrait mode. I tried it a couple of times an while reading websites was fantastic in this orientation there were many other applications that just didn't work well. Thanks to Visual Studio 2010 and multiple monitors I think I now have reached a state of nirvana.



One of the nice new features of VS 2010 is that it supports tearing off toolbars and code windows and positioning them outside of visual studio. In the screens above you can see that I have taken the tools window and moved it off to the left monitor - giving me enough width to see a full line of code. Without a second monitor things are just too narrow for this to be effective (unless you are a fan of the auto-hide features which I am not). Being able to see a huge vertical column of code definately reduces the aggravation of having to constantly scroll. I also like how much vertical room it leaves for the solution explorer, which leads to less expanding/collapsing of the tree to get to your files.

The leftmost monitor of course operates in landscape mode which in my mind is necessary to support apps that don't work well in portrait mode. Terminal services is a great example of this. I am constantly TS-ing into other boxes to perform updates/code pushes/etc and 1080 pixes of width on the portrait monitor just doesn't cut it.

Since I have adopted this setup I normally keep VS running on the right monitor maximized. The left monitor holds a half screen outlook and a half screen browser for reference purposes. When I am doing serious reading I use the Windows 7 window snapping shortcuts (Windows-Left/Right/Up) to move the browser to the portrait montior for some serious content absorption.



Of course this has me seriously considering a third landscape monitor for the right side....

0 Comments     follow

Login to post comments
Icon

ModalDialogManager - A simple approach to dealing with modal dialogs in MVVM

Wed Mar 3rd 2010 by Brett
The more I work with MVVM the more I like it. That being said when I started using the pattern early last year I would run into conceptual roadblocks that would halt my progress and kill productivity. One of those concepts that got me stuck was how to deal with modal dialogs. MVVM cleverly uses databinding to decouple the View from the ViewModel - and there is a lot you can do with databinding in WPF. Opening modal dialogs is not one of them.

The issue centers around the face that a Window in WPF cannot be added to a XAML document anywhere other than the root. This would prevent some kind of strategy where you inlined the window in the xaml and invoked the ShowDialog method via binding. (Aside from that - it would lead to some really huge and ugly XAML files.

I solved this problem by creating a Control called ModalDialogManager that I place in the View acting as the parent to the Modal dialog. This control has several properties - one of which called IsOpen which can be used to control the visibility of the dialog. There are also properties for controlling the size of the resultant dialog, resize mode, icon, and the ICommand to be called if the user clicks the Red X.
<Window>
     <Grid>  
          <Button HorizontalAlignment="Right" Command="{Binding ShowMessageCommand, Mode=Default}" 
             Content="{Binding ShowMessageLabel}" VerticalAlignment="Bottom" Margin="0,0,13,8">
          <Button Width="3" Height="0" HorizontalAlignment="Right" 
             Content="Button" VerticalAlignment="Bottom" Margin="0,0,-210,-256">  
 
          <!-- Define ModalDialogManager and wire up to ViewModel called MessageWindow --> 
          <local:ModalDialogManager Title="{Binding Title}" CloseCommand="{Binding OKCommand}" DialogResizeMode="NoResize"
             DialogWidth="300" DialogHeight="300" IsOpen="{Binding IsOpen}" DataContext="{Binding MessageWindow}" />  
          <TextBlock Margin="21,27,31,64" TextWrapping="Wrap" Text="{Binding Status, Mode=Default}"></TextBlock>  
     </Grid>  
</Window> 


There is one important thing that might not be immediately obvious - when the dialog is shown it will use the same DataContext as the ModalDialogManager. A content presenter at the Root of the modal dialog (Window) will be bound to the ViewModel. Therefore you have to use a DataTemplate to associate a View to this ViewModel. In the sample project I do this in App.xaml.

<DataTemplate DataType="{x:Type vm:MessageWindowViewModel}">
     <v:MessageWindow/>
</DataTemplate>
As soon as the MainViewModel invokes the IsOpen property on the MessageWindowViewModel the dialog will be show and code execution will be transferred to the MessageWindowViewModel. This is a boon, because setting IsOpen acts just like ShowDialog in that after the dialog is closed code excution will resume on the next line. Here are the interesting bits about how the ModalDialogManager class works.
        /// 
        /// This is invoked when the red X is clicked or a keypress closes the window - 
        /// 
        public ICommand CloseCommand
        {
            get { return (ICommand)GetValue(CloseCommandProperty); }
            set { SetValue(CloseCommandProperty, value); }
        }
        public static readonly DependencyProperty CloseCommandProperty =
            DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(ModalDialogManager), new UIPropertyMetadata(null));


        /// 
        /// This should be bound to IsOpen (or similar) in the ViewModel associated with ModalDialogManager
        /// 
        public bool IsOpen
        {
            get { return (bool)GetValue(IsOpenProperty); }
            set { SetValue(IsOpenProperty, value); }
        }
        public static readonly DependencyProperty IsOpenProperty =
            DependencyProperty.Register("IsOpen", typeof(bool), typeof(ModalDialogManager), new UIPropertyMetadata(false, IsOpenChanged));


        public static void IsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ModalDialogManager m = d as ModalDialogManager;
            bool newVal = (bool)e.NewValue;
            if (newVal)
                m.Show();
            else
                m.Close();
        }


        void Show()
        {
            if (_window != null) Close();

            Window w = new Window();
            _window = w;
            w.Closing += w_Closing;
            w.Owner = GetParentWindow(this);
            
            w.DataContext = this.DataContext;
            w.SetBinding(Window.ContentProperty, "");

            w.Title = Title;
            w.Icon = Icon;
            w.Height = DialogHeight;
            w.Width = DialogWidth;
            w.ResizeMode = DialogResizeMode;
            w.ShowDialog();
        }

        void w_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (!_internalClose)
            {
                _externalClose = true;
                if (CloseCommand != null) CloseCommand.Execute(null);
                _externalClose = false;
            }
        }

        bool _internalClose = false;
        bool _externalClose = false;

        void Close()
        {
            _internalClose = true;
            
            if (!_externalClose) _window.Close();
            _window = null;
            _internalClose = false;
        }

        Window GetParentWindow(FrameworkElement current)
        {
            if (current is Window)
                return current as Window;
            else if (current.Parent is FrameworkElement)
                return GetParentWindow(current.Parent as FrameworkElement);
            else
                return null;
        }

A sample project can be downloaded here. Sorry - no Silverlight version yet, but it is on the way.

11 Comments     follow

Hi,

This is by far the most clean and ingenious way I've yet seen to solve the problem of modal dialogs in MVVM. It took me quite some time to wrap my head around the way things work but now that I 'get' it, I find it a very clever way of maintaining a separation of the viewmodel and the view.

Thanks you for this. Maybe you could put up an article on CodeProject to give it more exposure?

Bye,
Steven
posted by Steven on Tue Mar 23th 2010 at 8:57 AM
Hi Steven-
Thanks for the feedback! Your right - I probably should post this on Code Project. I have actually made a couple of enhancements since this post to take into account dialogs that execute immediately upon launch (my use case was a cancellable progress dialog). I normally submit my Silverlight posts to Silverlight Cream, but I haven't been able to find a similar community for WPF. Code Project is probably the best bet.
Brett
posted by Brett on Thu Apr 1st 2010 at 1:43 PM
Fantastic code, and also nice silverlight spot to land it on - can you explain more about setting behavior for the red-x? I tried the code and could get code to execute in a function called by red x (using the CloseCommand set to redX() relay function), but as soon as it completed, the dialog closed. What would be really nice, is if we could also use your CloseCommand property to apply validation, such as 'do you really want to close this window' when the redX is pressed. Tell me what you think, and thanks for posting this.
posted by -=Chris=- on Thu Aug 4th 2011 at 7:41 PM
First, let me say this is the easiest explanation and code to follow for someone just starting to learn MVVM that I've found after hours of searching - thank you.

However, I do have a question about the code presented here and other places I've seen. From what I've found on the internet, it seems that to create a dialog pop-up and/or message box that you have to create a completely separate class (ModalDialogManager in this example) to control it, create a dialog template (MessageWindow.xaml), and a view model for that template. Yet, in the parent window's view model, you still invoke opening the dialog window.

So, my confusion, and lack of understanding, is why do all that when you can simply do MessageWindowObject.ShowDialog()? Is that bad for MVVM? It seems like that is what you (and other places I've read) are essentially doing in a round-about way. If you have an explanation or an article you could send me that explains it just as easily as this blog post, I would be grateful.
posted by BenL on Fri Aug 5th 2011 at 8:23 PM
-Chris
I like the idea of being able to apply validation logic when the CloseCommand is called. I think that the approach would have to along these lines:
1. Add an Func property to ModalDialogManager called bool ValidateClosing
2. Create such a Func in the underlying ViewModel supported by ModalDialogManager. (in the example above MessageWindowViewModel) bool CanCloseMethod
3. Bind the ValidateClosing property to CanClose
4. In the w_Closing event handler: if CanClose is not null Execute CanClose and test the result

-Brett
posted by Brett on Mon Aug 8th 2011 at 3:47 PM
-BenL
Thanks very much! It certainly would be much easier to do exactly what you suggest, and in fact on some projects I have provided some helper methods to simplify the user of the ModalDialogManager. However, to truly isolate the the View from the ViewModel there are some things that really need to live in the View(s). For instance
1. Dialog Configuration - Size, Modality, Position

I generally don't want any references in my view models to any of the UI namespaces. This serves as a sanity check to ensure my VM doesn't have any dependencies on the V. To invoke ShowDialog from a ViewModel some layer of abstraction needs to sit between it and the view to allow the communicate to take place. In this case ModalDialogManager is a clever way of using databinding to achieve this in a consistent manner. You could do the same thing with some View code-behind and databinding, but in time that could become a bit of a maintenance nightmare without the encapsulation of responsibility that ModalDialogManager achieves.

I should note that for achieving the equivalent of MessageBox.Show I will often declare a helper method on AppManager class that simplifies the entire process - it is connected to a single ModalDialogManager that appears in root visual of my application. Then from the ViewModels I can simply call AppManager.ShowMessage (or somesuch) without the drudgery of having to add all the extra xaml for such a simple need.

-Brett
posted by Brett on Mon Aug 8th 2011 at 4:02 PM
Thanks for sharing this. To me, this approach makes the most sense compared to other alternatives.

But now I would like to know whether it is possible to define the DataTemplate at the Window resources level. My preference is to have the template defined as close as possible to where it's being use. Do you know any way to support this use case?

-Luthfi
posted by luthfi on Fri Oct 28th 2011 at 8:28 AM
As a MVVM noobie I'm loving this straightforward and clear approach to modal dialogs. A few more properties on the ModalDialogManager (like WindowStartupLocation, WindowStyle, etc) are nice and easy to add in. Again as a noobie though ... I'm failing to see how to set/return a result - is OK or Cancel pressed for example. All button actions call OKCommand. How to get around this?

But before I go - thanks for the great post, it really was most useful indeed.
posted by Toot on Tue Mar 6th 2012 at 4:50 PM
Thanks a lot for this excellent concept! Since I am adapting an existing application to use it, I made a generic class out of it, in Visual Basic: ModalDialogManager(Of T As Window). That allows me to pass the type of the window I want to show to the modal dialog manager and allows me to instantiate any window I already defined in my application. That saves me from turning a dozen of windows into user controls. It also allows me to define the window properties like its size in the window's XAML or in its ViewModel, instead of having to add it to the ModalDialogEditor. That is probably slightly more elegant. Since generic controls cannot be defined in XAML, I created a inherited class for each dialog-window type.

-cucucucu
posted by cucucucu on Sat Jun 30th 2012 at 12:16 AM
Thanks for this easy to understand solution.
I was looking for a solution of this problem for some time and all the other solutions were quite complicate.
You approach is elegant and thus very useful!

-Tom
posted by tomsabeom on Thu Sep 20th 2012 at 5:51 AM
Thanks for this solution. It is really the best one I have seen on this topic and it helped me a lot with my own application.
But I have a question about closing the Window:

Is there a way to close the window from a button inside the UserControl instead of the red X?
(e.g when Window.Style=None)

posted by darkmoon221 on Thu Nov 7th 2013 at 8:07 PM
Login to post comments
Icon

SyncToy 2.1 - A very useful and free tool for syncronizing your files

Thu Feb 25th 2010 by Brett
I have a pretty common problem in my household - my wife and I need to share files, but also have access to them we take our laptops off the network. Up until this point we used Windows Offline files. I created shares on the network for all of our "My" folders (documents/pics/music/etc) and moved the location in our profiles to point to those locations. Windows automatically sets them up as offline folders and syncs the files back and forth. This allowed us to share things like our photos and music.

Unfortunately we are users of iTunes. We are forced to do so because we have iPhones (all though not for long - the 7 series phones look great). For whatever reason iTunes would often lose its database including all the playlists etc. This happened more than once, even after complete system rebuilds. I am not sure why this was the case but I suspect that iTunes just wasn't playing nicely with the behind the scenes sync mechanism that Offline files uses. (It uses a local cache that it will dynamically redirect you too if you become disconnected) Also - because all of our My folders were UNCs there were some applications that didn't like that. (CAS in Visual Studio and Live Movie maker are examples)

Now I could disable the Offline Files and just use network shares, but what I like about the sync is that it also gives me better data redundancy. If my workstation dies I have all my important bits on the server as well as a few other machines. Conversely a down server wont stop me from getting access to my files.

I found a replacement that is built on the Microsoft Sync Framework called SyncToy. SyncToy lets you build folder pairs and perform bi-directional sync between them. You can then schedule a sync via Task Scheduler which will automatically propagate your changes. There are some nice options including Syncro (bidirectional sync), Echo (pushes changes in one direction only), and Contribute (which only pushes add/modify/renames in one direction).

So far so good, but I have only been using it for a few days - I'll update this post after I have lived with it for a little while. Download SyncToy 2.1 here.

0 Comments     follow

Login to post comments
Icon

Connecting XBox 360 MCE to Windows 7 in a Domain

Fri Feb 19th 2010 by Brett
I have been having problems getting my XBOX 360 to connect to my Windows 7 Media Center for the last year. I never spent the time to get it working until today. After I performed the normal steps for adding and extender (which would complete successfully) I would get errors on my 360 saying that it could not connect the the Media Center. Sometimes I would get as far as the MCE start page, other times it would fail on the screen with the little white dots below the WMC logo. In any case I found the solution:

Solution
Run gpedit.msc. Go to Computer Configuration -> Administrative templates -> Windows Components -> Remote Desktop Services -> Remote Desktop Session Host -> Security.

Enable "Set client connection encryption level" & change encryption level to 'Client Compatible'. Disable "Always prompt for password upon connection"

I'm guessing these settings don't only apply to Windows 7, but to Vista and XP media centers as well.

0 Comments     follow

Login to post comments
Icon

Introducing TagBox

Tue Feb 16th 2010 by Brett
Recently I wanted to write a TO: box in a Silverlight that worked similar to the one Outlook has. It is a neat control that allows you to "resolve" items based on text matching. Unlike a standard AutoComplete box this control allows you to "resolve" multiple items inline. Once an item is resolved it acts as a cohesive element instead of individual letters - what I call a tag. The tag (a resolved email address in Outlook) can be clicked on which brings up more information about the address. A number of popular sites use this style of control (js based) including Hotmail (the To box obviously) and Facebook (their email function).

Effectively this control allows you to build one-to-many relationships between an email and its intended recipients in a very natural way. Obviously the key to this control working effectively is the excellent keyboardability (is that a work?) that it offers. Aside from the usage described above there are a number of cases where such a control would be useful. One example might be applying a set of categories to a blog post. In an online store example it might be used to define the areas of the store where an item might appear. This control is extremely effective when the relationship between the entities is simple - it can track the relationship and the order of the relationship but no additional data about the relationship.

Example

This example starts with our familiar case of an Email where the user would like to enter a number of email addresses. If you start typing an address it performs an async search for the email address based on name and address. A popup is displayed if matches are found without losing your position in the TagBox and you can presss up and down to navigate the matches. Also - if you enter a valid email format such as test@test.com, you will see it appear in the bound listbox to the right. This control was designed to be databound, and in particular work well in MVVM Patterns.

There are a few interesting properties on the Control:
  • ItemsSource – IList value represents the set of resolved matches in the control. It also supports INotifyCollectionChanged so it can be bound to ObservableCollection allowing external changes to be propagated to the control automatically.
  • DisplayMemberPath – I used a similar name here to what the ListBox control uses to determine which property is displayed when the results are shown either in the tags or the search results.
  • SearchMethod –a Action dependency property provides the logic for taking the text entered and execting a query/lookup that in turn returns SearchResults. This method can be synchronous or asynchronous, so long as the returned results are placed in SearchResults.
  • SearchResults – to support Synchronous or Async searching, when this property is populated search results are shown to the user. Make sure the class to which SearchResults is bound to implements INotifyPropertyChanged so TagBox is aware of SearchResult changes.


In an MVVM scenario the four important properties above you can simply bind these values to a ViewModel. In my example I have an EmailViewModel (implement INotifyPropertyChanged) which is bound as follows (position omitted for clarity).
<tsm:TagBox SearchMethod="{Binding SearchMethod}" SearchResults="{Binding SearchResults}"
          DisplayMemberPath="DisplayName" ItemsSource="{Binding To, Mode=TwoWay}" />
  • ItemsSource -> To (ObservableCollection)
  • DisplayMemberPath = “DisplayName” which is a property of Contact
  • SearchMethod -> SearchMethod(Action which points to a method FindMatchingContacts(string))
  • SearchResults -> SearchResults(IEnumerable)


The following code illustrates the implementation of SearchMethod in EmailViewModel.cs. You will note that although this is a synchronous method in this example SearchResults can be populated as a result of an async web service invokation.

        #region SearchMethod (INotifyPropertyChanged Property)
        private Action<string> _searchMethod;
        public Action<string> SearchMethod
        {
            get { return _searchMethod; }
            set
            {
                if (value == _searchMethod) return;
                _searchMethod = value;
                base.OnPropertyChanged("SearchMethod");
            }
        }
        #endregion

        public void FindMatchingContacts(string searchText)
        {
            if (searchText.Length >= 1)
            {
                var contacts = from cs in ContactCollection.Members
                               where cs.EmailAddress.StartsWith(searchText, StringComparison.InvariantCultureIgnoreCase) 
                                    | cs.DisplayName.ToLower().Contains(searchText.ToLower())
                               select cs;

                SearchResults = contacts.ToList();
            }
            else
                SearchResults = null;
        }
Fig 1. Code from EmailViewModel.cs demonstrating search method

The control does all the heavy lifting and it simply needs to be provided with search logic and search results. This fits well with MVVM and the ViewModel in my example could easily be bound to entirely different lookup UI not dependent on TagBox.

Validation

This aspect of the control probably gave me the most consternation. At a high level the control is dealing with a non homogenous collection of item types. In the example of an email TO: box we have:

  • Contacts: resolved items that were matched via search
  • Text Addresses: unresolved items that may have been entered by the user


In the email case – text addresses are perfectly fine, so long as they pass some kind of validation. So the question became – how do you deal with a non-homogenous collection of items without it being a mess on the ViewModel side (or the non-control side if not using MVVM). Initially – I dealt with the problem by creating two collections – one for resolved that was used for databinding – and another for unresolved that was readonly (trying to synch two collections to the UI was going to be awful). As I got into it I realized this was about as good an idea as a “Larry the Cable Guy” movie (e.g. bad idea).

I realized that ideally the collection would be homogenous, but how to convert text entries into strongly typed objects. I didn’t want to have to expose a special container class outside the control as it would corrupt the layer of separation I was trying to achieve. Ultimately I added an Func UnresolvedValidationMethod property to the TagBox where you can specify your own function for examining the text entered and returning it classed as your bound object type. In the email example I check the format of the address and return a Contact. The great thing about this is that on the ViewModel side you have a single collection that holds all the addresses, and ultimately you could decide how to deal with these newly created contacts. (for example – you could just send a message to them, or you could save them to your Contact repository when you detect that their Ids are 0)

Lastly – there could exist a set of unresolved items that would not validate (if you entered ASDF as an email address for example). These are not included in ItemSource, but can be found in InvalidItems. The logic here is that if we cannot pass the Validation method then they are not robust enough to be included in that set. Instead they are decorated (a dashed underline OOB) and you can decide how to handle them. Common ways would be

  1. In an email scenario – do not allow the message to be sent until they are corrected – could present a custom UI for correcting them.
  2. Prompt and allow them to be discarded
  3. Discard them automatically


Validation Properties

  • ValidateUnresolved – boolean property indicates whether or not validation should be performed – if true an UnresolvedValidationMethod must be provided
  • UnresolvedValidationMethod – Function takes a text entry and converts it to an object compatible with the objects stored in ItemsSource. Once validated the text entry, now a correctly typed object, is placed in ItemsSource in the correct location.
  • VisualState “Invalid” – The UnresolvedTag control template contains an “Invalid” state that can be customized. It is set whenever text cannot be validated.

The following code demonstrates the UnresolvedValidationMethod as implmented in EmailViewModel.cs. Note - asynchronous validation is not supported at this point.

        public Contact IsValidEmailAddress(string email)
        {
            bool valid = Regex.IsMatch(email, @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                                              @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                                              @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
            Debug.WriteLine("Valid Email? " + email + " " + valid);
            if (!valid) return null;
            return new Contact() { DisplayName = email, EmailAddress = email };
        }
Fig 2. Code from EmailViewModel.cs demonstating text validation

Customization

TagBox is implemented as a CustomControl, meaning that its templates can be customized very easily to provided a dramatically different looking appearance. There are 3 main templates that can be customized

TagBox – this template is responsible for the actual border around the TagBox and the panels that hold the tags. OOB – it is essentially a ScrollViewer that contains a WrapPanel and a Popup (search results container)



ResolvedTag – after an item is resolved it gets translated into a ResolvedTag. OOB it has a rounded border with an X so you can remove an item from the tagbox with the mouse. A custom template could be used here to display more information about the tag if so desired. DataBinding occurs in the Content field by default.


UnresolvedTag – this holds the text entered prior to being resolved. It is a pretty simple template who’s most important component is a TextBox with very little styling.



The example below has been restyled to be more appropriate to a set of categories. (Templates are included in the sample project)



Licensing

Although I am not releasing the source code for this control, I am allowing folks to make use of the control for use in personal projects. I go back and forth on the free versus paid approach and my general rule of thumb is that if it takes me more than a week to build something, and I intend on supporting it in the future, it is worth a nominal fee. In this case I ended up putting a little under 3 weeks into the project and documenation and I think it has a lot of value.

Watermarked Control – you may use the control for non-commercial purposes so long as the "thesilvermethod.com" watermark is visible.

Business License - a non-watermarked version of the control is available. I haven't gotten my act together yet on setting up the online purchasing, but in the short term if you would like to use this, please contact me directly - bbalmer@setpowersoftware.com.

Updated 2-23-2010 You can now purchase developer licenses for TagBox here. After purchasing a license a link will be emailed to you that will allow you to download a non-watermarked version of the TagBox assembly.

Here are the details of the license.

Demo Code includes TagBox assembly and demo project shown in this blog post.

6 Comments     follow

Any chance you would consider adding support for SelectedItem? I have a scenario where I am performing a second layer of validation on the submission of my form. If I detect certain objects I would like to notify the user and have the focus set on that object. Sweet control BTW. Jim
posted by jWalker on Wed Feb 24th 2010 at 3:39 PM
Jim- that is an interesting idea and at first blush not that difficult to do. I hadn't really considered using SelectedItem for that (instead I raise events for selection) but I like the idea because it would support databinding for other use cases. For example suppose when an email address got focus that we would show relationship information or a picture to the right of the TagBox. Let me see what I can do.
posted by Brett on Wed Feb 24th 2010 at 3:48 PM
Jim - I just updated the release to v.1.0.0.3 which includes support for SelectedItem. The demo project in the download also has code demonstrating the use of hte property. It is two-way bindable so if you update SelectedItem it will be reflected by the focused item in TagBox.
posted by Brett on Wed Feb 24th 2010 at 6:19 PM
Hi Ken-
I would check to make sure that all the necessary properties are configured: ItemsSource,DisplayMemberPath,SearchMethod,SearchResults

feel free to followup with me via bbalmer at setpowersoftware.com
posted by Brett on Wed Feb 23th 2011 at 3:47 PM
The current version of this TagBox allows the SearchMethod property of a type ICommand insteaf of Action string...?
posted by jmartarelli on Wed Mar 30th 2011 at 6:29 PM
Hello, Im testing this control in my project and it really attends my needs but there is a bug in it. When I choose an item from a list and right after press enter again and again... it duplicates the item in the resolved list.

How do I solve it?
posted by jmartarelli on Wed Apr 6th 2011 at 1:07 PM
Login to post comments
Icon

Drag and Drop Upload to Azure Storage via Silverlight 4

Thu Jan 21th 2010 by Brett
I recently needed a way to upload images and other files to Windows Azure Storage. I like the way some sites implement ActiveX controls or other plugins that allow you to drag and drop the files onto the browser itself for upload. Naturally when I read about the new capabilites of Silverlight 4 to accept dropped files I was dying to write a little upload control. This blog is hosted on Windows Azure, and as mentioned in previous posts, the blog-entry content files (images/xap files) are stored in Windows Azure Storage.
Fig 1. screenshot of upload control with 4 files
I did a quick search for Silverlight upload controls and came across an interesting project on CodePlex being worked on by Darrick C (thanks!). This project saved me quite a bit of time as it already had code for transferring a file from Silverlight to IIS. The code supported very large file sizes and larger chunk sizes than a webservice upload would generally support. There were some additional features there as well, that I didn't care about, but would mention should anyone else be interested, such as image re-sizing and upload resume.

Now on to the interesting parts:
Drag and Drop support - accepting a file drop event in SL4 is extremely easy. You can accept a drop from any control that derives from UIElement by setting AllowDrop=true.
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="55"></RowDefinition>
            <RowDefinition Height="437*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="75"/>
        </Grid.ColumnDefinitions>
        <TextBlock HorizontalAlignment="Left" Margin="5,5,5,0"  Name="textBlock1" 
                   Text="Drag and Drop Files Below" VerticalAlignment="Top" />
        <StackPanel Grid.Column="1" >
            <Button Content="Upload" Name="button1"  Click="button1_Click"  />
            <Button Content="Clear" Margin="0,5,0,0" Click="Button_Click" />
        </StackPanel>
        <ScrollViewer x:Name="ImagesTarget" Background="WhiteSmoke" AllowDrop="True" Grid.ColumnSpan="2" Grid.Row="1">
            <ItemsControl x:Name="ImagesList">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <controlsToolkit:WrapPanel Orientation="Vertical">
                            <Image Source="{Binding Image}" Margin="5" Stretch="Uniform" MaxHeight="100" MaxWidth="100" />
                            <ProgressBar Value="{Binding FileUpload.UploadPercent}" Margin="3" Height="10"/>
                        </controlsToolkit:WrapPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <controlsToolkit:WrapPanel />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </ScrollViewer>

    </Grid>
You can see in my case I am allowing drop on the ScrollViewer named ImagesTarget. In the code-behind I attach an event handler to the ImagesTarget.Drop event:
        public UploadControl()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            ImagesList.ItemsSource = _images; 
            ImagesTarget.Drop += new DragEventHandler(ImagesTarget_Drop);
        }

        void ImagesTarget_Drop(object sender, DragEventArgs e)
        {
            if (e.Data == null) return;

            IDataObject dataObject = e.Data as IDataObject;
            FileInfo[] files = dataObject.GetData(DataFormats.FileDrop) as FileInfo[];

            //create a collection of FilePair for databinding
            foreach (FileInfo file in files)
            {
                try
                {
                    FilePair pair = new FilePair();
                    using (var stream = file.OpenRead())
                    {
                        var imageSource = new BitmapImage();
                        try
                        {
                            imageSource.SetSource(stream);
                        }
                        catch 
                        {   //it is not an image - lets show a default icon
                            imageSource.UriSource = new Uri("unknownfile.png", UriKind.Relative);
                        }
                        pair.Image = imageSource;
                    }
                    pair.FileUpload = new FileUpload(this.Dispatcher, UploadUri, file);
                    _images.Add(pair);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unknown error prepping file for upload: \n" + ex.ToString());
                }
            }
        }
You can see that we try to load the files as images so that we can show thumnails in the UI, defaulting to a generic icon in cases where the file is not an image. Through databinding the files are then shown in the UI as a thumbnail and a progressbar. The work of uploading the file is performed by the FileUpload class which communicates with the HTTPHandler using querystring parameters. It also raises events when the upload of the file is complete. There are a couple of things I don't like about this class, one of which is the fact that the function of uploading the file is intermingled with UI telling the users the file already exists on the server. Since this was a quick and dirty for my own personal use I didn't refactor this yet (this code is largely unchanged from the codeplex project), but I would put it high on the list.

Storing the File in Azure - the HTTP handler does a couple of things.
  1. Creates a Container in Azure for holding uploaded files if it does not already exist.
  2. Checks to see if the file already exists in Azure
  3. Listens for chunks of an incoming file writing them to a temporary file in the filesystem. I wanted to avoid this step, but I couldn't find a way to append to a file in Azure storage.
  4. Writes the file to Azure Storage and deletes the temporary file.
The heavy lifting is done in a class called AzureFileUploadProcess. A couple of interesting bits of code:
       //the first time this method is called lets make sure our container is setup properly non-authenticated users have permissions 
        // to access files in the Azure container.
        void Initialize(HttpContext ctx)
        {
            CloudBlobClient client = CloudStorageAccount.FromConfigurationSetting("StorageAccount").CreateCloudBlobClient();

            //containers must be lower case - this seems strange to me but I cannot get it to work with uppercase 
            CloudBlobContainer container = new CloudBlobContainer(_containerName, client);
            container.CreateIfNotExist();
            container.SetPermissions(new BlobContainerPermissions() { PublicAccess = BlobContainerPublicAccessType.Blob });
            _container = container;
        }
The above code is responsible for creating the Azure Container. Containers in Azure can most be thought of as specialized file directories. They can define metadata that applies to the files they contain and also can have permissions. In the above code I create the container and allow public access to it (wouldn't do my much good to upload images no-one could get to).

Next is some code demonstrating check Azure Storage for file existence
                CloudBlob blob = Container.GetBlobReference(filename.ToLower());
                try
                {
                    blob.FetchAttributes(); // this will throw an exeception if it does not exist
                    context.Response.Write(blob.Attributes.Properties.Length);  //report the size of the file
                }
                catch (Exception) { context.Response.Write("0"); }  //I don't let checking for existence via exception handling, 
                                                                    // but that was the recommended/only approach on the MSFT blogs.  
                context.Response.Flush();
And finally we write the file to Azure and delete the temporary file
                       CloudBlob blob = Container.GetBlobReference(filename);
                        blob.UploadFile(filePath);

                        File.Delete(filePath);  //we stored this in a temporary area - delete it now that we are done

                        FileUploadCompletedEventArgs args = new FileUploadCompletedEventArgs(filename, blob.Uri.ToString());
                        FileUploadCompleted(this, args);

In the attached project I actually included an UploadProcess that is just designed to work against the FileSystem for those of you who aren't using Azure. As you can imagine, the code is not all that different from the Azure code.

Obviously this is not intended as the be-all-end-all of file upload controls. There is a lot of room here for neat things like
  1. Show the list of files already on Azure, presumably so you could delete/move/rename them.
  2. The ability to pause an upload via the UI
  3. Set metadata in Azure storage to futher categorize the files
  4. This should really be implemented as a custom control so that the UI can be re-styled more easily.
A Visual Studio 2010 project can be found here with all the code. I should note that you will need to have the Azure tools installed for this to work. Presently the project is setup to use the local Development Storage so you can test it without having to setup a service on Azure. Also - for some reason on my machine when debugging I cannot drop files onto the control (the mouse cursor even indicates it won't work). The solution is to open an entirely new browser and test it there.

11 Comments     follow

This is a great sample of using SL4 and Azure. I have the same issue when I debug the code in VS2010. Yes, I can run the second browser window to drop files, but I cannot debug in this case. Have you resolved this problem? If there any work around? I am thinking to enhance your sample into a full functional photo album management site. Of course, for free. What's on your mind?

KevinZ
kevin.zhang.canada at gmail dot com
posted by KevinZ on Sun Mar 14th 2010 at 7:34 AM
I set Chrome as default browser and start debug your application. I can drag drop files into chrome. But this won't work in IE (Windodws7). I think there may be a problem in IE with Silverlight 4.

BTW, I think the FileUploadProcess.cs is useless. You did not really use the class. It has been replaced by the Azure version.

posted by KevinZ on Mon Mar 15th 2010 at 5:09 AM
Hi Kevin -
Did you try this on SL4 RC yet? Since this was written on SL4 Beta I wonder if the debugging issue has since been corrected. I plan on trying it out later this week.

BTW - I included the FileUploadProcess.cs just in case someone wanted to use it in a non-azure screnario.
posted by Brett on Thu Mar 18th 2010 at 12:50 PM
I tried in VS2010 RC with SL4 RC, still the same problem. You can double check.
posted by kevinz on Thu Mar 18th 2010 at 11:41 PM
I was wondering if uploading a large file in chunks will break in a load balanced scenario. Since each post could go to a different server, isn't it possible that individual chunks could get written to different temporary files?
posted by Ozzy on Wed Mar 31th 2010 at 10:38 AM
Hi Ozzy - A load balancer would probably have to be taken into account unless it supports sticky sessions. If it didn't then one simple approach would be to write the chuncks to a shared network location instead of a local path on the balanced server. Of course that would result in a single point of failure, but you could always program in a rollover location if the first server couldn't be reached.
posted by Brett on Thu Apr 1st 2010 at 1:22 PM
Kevin-
Regarding debugging drag and drop: I was debugging a totally unrelated Outlook Addin and while in my debugging session I couldn't drag and drop items into Outlook either. I looked into it and it turns out the problem is that UAC prevent drag-drop operations between processes executed by diffent accounts. In my case I was running visual studio as Administrator (elevated). Once I switched to running Visual Studio in non-elevated mode I was fine. I just tried it for this project and it also worked - sort of. Because the Azure Tools require VS to be run elevated you cannot debug the solution end-to-end. Kind of a catch-22. Supposedly if you disable UAC then this is a non-issue.
posted by Brett on Thu Apr 1st 2010 at 1:39 PM
Brett, this is a great post, and a great example. I have a follow up question regarding downloading as opposed to uploading. I want the Silverlight 4 app to be able to download a file given that the SL app knows the blob container and filename on Azure. However, I don't want to leak any Azure keys to the SL4 client.

Specifically, let's say that the SL4 app accesses a record from SQL Azure, which contains the blob filename. Similar to your upload example, the SL4 app would communicate with the server, passing the filename, and have it downloaded into SL4's memory for displaying. Only the server would know how to specifically access blob storage (just like your upload example). Any examples or direction you could give would be appreciated.
posted by spbgeb on Fri Jul 16th 2010 at 10:21 PM
Ozzy & Brett, to solve the load-balancing issue, what about copying the files to a container that contains ONLY temp files, then move (copy) the file to the destination container once it is uploaded. Can you think of any downsides to this approach? I believe this solves the load-balancing issue in that the destination is always known and is not local to the server, and does not clutter up the desitination container.
posted by spbgeb on Sat Jul 17th 2010 at 11:10 PM
spgeb:
Regarding downloading files: I assume that the files you want the SL client to download are non-anyonymous files, otherwise you wouldn't need the key - just the Url. Assuming that is the case you could generate a shared access signature that you would pass to the SL client for download. I haven't done this myself, but here is an article that discusses the concept. http://blog.smarx.com/posts/new-storage-feature-signed-access-signatures

Regarding load balancing: Yes - I think that would work, with the only downside being that you are going to generate a lot of traffic between the webservers and the shared location as each file will consume the (file size/divided by the chunk size )! * chunk size unless you can append to the file in the shared location. I was just doing some reading and it looks like some folks have tried an approach where they are using PutBlock to append to an Azure Blob. http://social.msdn.microsoft.com/forums/en-us/windowsazure/thread/C60EB581-A503-463F-A102-E4A54099EB18 That would be the best way to handle the situation, other than the fact you would have to delete incomplete uploads otherwise they would sit in Azure Storage forever.
posted by Brett on Mon Jul 19th 2010 at 3:32 PM
Hi everyone,

Thanks a lot Brett for this post, this is of considerable help.
I am currently working on a web app that used "standard" upload on a server, and could get this working using Azure storage thanks to your article.

I noticed the server returns to the client when it has uploaded the file, but the blob may not have been uploaded to Azure storage yet. Using this proxy, there is a delay which comes from the asynchronous call (in the AzureFileUploadProcess handler):
blob.UploadFile(tempFileOnServer)...

Is there a way for the client to wait for the blob to be created on Azure storage before saying "congrats, you successfully uploaded N documents..." ?

Again, thanks for this great post. Any help on this would be particularly appreciated!
Cheers
Raphaël
posted by repplst on Mon Nov 1st 2010 at 11:21 AM
Login to post comments
 

Recent Posts

By Month