Help, I just graduated but I don’t feel like I know how to program!

May 12, 2012

There was a great question on Programmers about graduating with a programming degree, but not knowing how to program. I see this kind of question a lot, and I felt the same way when I first got my degree, so I thought I’d write about my experiences and what I learned when first started programming.

This was originally an article I wrote for the Programmers.SE blog, however the blog doesn’t appear to be happening at this time so I am posting it on my own blog instead.


Start with baby steps

First off, don’t expect to be able to code enterprise-level applications or the next Facebook right away. You really can’t become a good programmer without a lot of practice, so practice any way you can. This can include hobby projects, reading books or source code, or even answering questions on Stack Overflow.

The book Outliers: The Story of Success frequently states that to become a master in any field you need to practice it for a total of 10,000 hours. In case you don’t want to do the math, that’s about 3.5 years of programming 8 hours every single day. If you only program during business hours at work, that’s almost 5 years.

Don’t discount your education

Rachel - Graduation Picture
When I first started working, I felt my education was worthless; that it just taught me stuff that was never used in the workplace. I soon realized it provided me with something better than syntax: it provided me with a good foundation for programming. For example, it didn’t teach me design patterns, but it did teach me what design patterns were and how / when to use them. And I might not have built a data access layer in my class projects, but I knew what they were for and when to use them.

It also provided me with resources such as books, an online library, and networking contacts in the industry. In addition, it gave me a fancy piece of paper which can be very useful for getting your foot in the door when you don’t have experience.

Of course, it didn’t teach me everything. Looking back I wish I had been taught about things like Version Control and Unit Testing. But they did their best to provide me with a solid foundation to build upon in the short time I was there, providing I was willing to go out there and keep learning.

Always be learning

One of the first things I got taught in college was that to be an IT professional, you really need to be a life-long learner. You can’t just graduate and expect you’ll have everything you need to get a high-paying job for the rest of your life. You’ll need to be willing to spend the rest of your life learning new technologies and languages.

Whenever I come across something new, something I don’t understand, or something I’m not sure of how to do, I Google it. Most of the time I can find a simple definition or samples, and I can start from there. If I do start from samples, I hate just blindly copying/pasting. I always take the time to understand what the code does. It might be slower to start with, however once understood it makes me that much better of a programmer.

Remember, N years of experience means nothing if it was simply 1 year repeated N times. There are plenty of jobs out there that are that will let you accumulate years of experience without you ever needing to learn anything new, however I feel you simply cannot be a great programmer without continuing to learn.

Steps to success in programming projects

Here is a list of steps to success in any project as a new programmer:

  • Be positive when asked if you can do something.

    If someone asks you if you can do something, be positive in your response. Answering negatively, or even indecisively, will often result in a lost opportunity to learn and grow, so avoid that unless the task is truly outside the realm of possibility.

    I usually use terms like “I don’t see why not” or “shouldn’t be too hard”. You may not know how to do it right away, but you should have the tools (Google!) and intelligence needed to figure out how to get it done. I like to avoid actually saying “yes” unless I know I can actually do what is being asked.

  • Determine requirements.

    Sit down with your client (boss, customer, etc) and figure out what they want. I’m not going to go into details of gathering requirements here, but do take the time to draw out the screens they expect to see, and to determine the expected input / output. My favorite tool for screen mock-ups is Balsamiq (its free!).

  • Figure out how to build it.

    This is one of the most important steps. A huge part of programming (especially early on) is figuring out what your client wants, and then learning how to do that. Don’t just stick with your own knowledge base!

    For new programmers, I would suggest just focusing on just getting the desired results. Don’t get bogged down trying to learn design patterns, architecture, test-driven development, etc. Learn the basics of how to program first, then expand on that knowledge. And remember, keep it simple! You don’t need an enterprise-level solution for the FizzBuzz problem.

    At this point, if you determine that the project is completely out of your scope, say so. Even if you determine the project is far too large or complex for you to build, you will have at least increased your own knowledge, so I always see it as a win-win situation.

  • Build it.

    You might think this is the hardest step of all, but in reality it will eventually become one of the easiest ones. Gathering the requirements and figuring out how you’re going to build the application are much more important, and if done right, it will make this step a breeze.

    Of course, early on in your career this step will be the most time-consuming and frustrating one. It will likely consist of a lot of trial and error, but don’t be disheartened because this means you are learning! We learn much more from our mistakes than from our successes, and the more you learn, the better your programming skills will become.

Summary

So to summarize, don’t worry too much about not being able to build / understand enterprise-level applications straight out of college. Start small, and keep an always be willing to learn. Work on programming for results first, and worry about best-practices later on. Hobby projects are a great way to gain experience. And remember, don’t ever stop learning!


Validating Business Rules in MVVM

January 22, 2012

I’ve always thought that raw data validation should occur in the data Model, while Business Rule validation should occur in the ViewModel.

For example, verifying that a UserName is no longer than X length long should occur in the data model, while verifying that the UserName is unique would occur in the ViewModel. The reason for this is that the User Model is simply a raw data object. It doesn’t contain any advanced functionality like database connectivity, or knowing about other User objects. It’s a selfish little thing which only cares about it’s own data.

Since I use IDataErrorInfo for my validation and like to expose the entire Model to the View from my ViewModel, this presents a problem. Using the above example, I could bind a TextBox to SelectedUser.UserName, and it would automatically show an ErrorTemplate if the string was too long, however it wouldn’t show an error template if the UserName already exists.

After some thought, I decided to add a Validation Delegate to my Models to solve this problem. This is a delegate which ViewModels can use to add Business Logic Validation to its Models.

In the above example, the UsersViewModel might look like this:

public class UsersViewModel
{
    // Keeping these generic to reduce code here, but they
    // should be full properties with PropertyChange notification
    public ObservableCollection<UserModel> UserCollection { get; set; }
    public UserModel SelectedUser { get; set; }

    public UsersViewModel()
    {
        UserCollection = DAL.GetAllUsers();

        // Add the validation delegate to the UserModels
        foreach(var user in UserCollection)
            user.AddValidationDelegate(ValidateUser);
    }

    // User Validation Delegate to verify UserName is unique
    private string ValidateUser(object sender, string propertyName)
    {
        if (propertyName == "UserName")
        {
            var user = (UserModel)sender;
            var existingCount = UserCollection.Count(p => 
                p.UserName == user.UserName && p.Id != user.Id);

            if (existingCount > 0)
                return "This username has already been taken";
        }
        return null;
    }
}

The actual implementation of my IDataErrorInfo on my Model class would look like the code below. It’s generic, so I usually put it into some kind of base class for my Models.


    #region IDataErrorInfo & Validation Members
    
    #region Validation Delegate
    
    public delegate string ValidationDelegate(
        object sender, string propertyName);
    
    private List<ValidationDelegate> _validationDelegates = new List<ValidationDelegate>();
    
    public void AddValidationDelegate(ValidationDelegate func)
    {
        _validationDelegates.Add(func);
    }

    public void RemoveValidationDelegate(ValidationDelegate func)
    {
        if (_validationDelegates.Contains(func))
            _validationDelegates.Remove(func);
    }
    
    #endregion // Validation Delegate
    
    #region IDataErrorInfo for binding errors
    
    string IDataErrorInfo.Error { get { return null; } }
    
    string IDataErrorInfo.this[string propertyName]
    {
        get { return this.GetValidationError(propertyName); }
    }
    
    public string GetValidationError(string propertyName)
    {
        string s = null;

        foreach (var func in _validationDelegates)
        {
            s = func(this, propertyName);
            if (s != null)
                return s;
        }
    
        return s;
    }
    
    #endregion // IDataErrorInfo for binding errors
    
    #endregion // IDataErrorInfo & Validation Members

The idea is that your Models should only contain raw data, therefore they should only validate raw data. This can include validating things like maximum lengths, required fields, and allowed characters. Business Logic, which includes business rules, should be validated in the ViewModel, and by exposing a Validation Delegate that they can subscribe to, this can happen.


Navigation with MVVM

December 18, 2011

When I first started out with MVVM, I was lost about how you should navigate between pages. I’m a firm believer in using ViewModels to do everything (unless it’s View-specific code), and that the UI is simply a user-friendly interface for your ViewModels. I did not want to create a button on a page that has any kind of code-behind to switch pages, and I didn’t like the idea of my navigation being spread out throughout all the ViewModels.

I finally came to realize the solution was simple: I needed a ViewModel for the Application itself, which contained the application state, such as the CurrentPage.

Here is an example that builds on the Simple MVVM Example.

The ViewModel

Usually I name the ViewModel ApplicationViewModel or ShellViewModel, but you can call it whatever you want. It is the startup page of the application, and it is usually the only page or window object in my project.

It usually contains

    List<ViewModelBase> PageViewModels
    ViewModelBase CurrentPage
    ICommand ChangePageCommand

Here is an example ApplicationViewModel that I would use to go with the Simple MVVM Example.


    public class ApplicationViewModel : ObservableObject
    {
        #region Fields

        private ICommand _changePageCommand;

        private IPageViewModel _currentPageViewModel;
        private List<IPageViewModel> _pageViewModels;

        #endregion

        public ApplicationViewModel()
        {
            // Add available pages
            PageViewModels.Add(new HomeViewModel());
            PageViewModels.Add(new ProductsViewModel());

            // Set starting page
            CurrentPageViewModel = PageViewModels[0];
        }

        #region Properties / Commands

        public ICommand ChangePageCommand
        {
            get
            {
                if (_changePageCommand == null)
                {
                    _changePageCommand = new RelayCommand(
                        p => ChangeViewModel((IPageViewModel)p),
                        p => p is IPageViewModel);
                }

                return _changePageCommand;
            }
        }

        public List<IPageViewModel> PageViewModels
        {
            get
            {
                if (_pageViewModels == null)
                    _pageViewModels = new List<IPageViewModel>();

                return _pageViewModels;
            }
        }

        public IPageViewModel CurrentPageViewModel
        {
            get
            {
                return _currentPageViewModel;
            }
            set
            {
                if (_currentPageViewModel != value)
                {
                    _currentPageViewModel = value;
                    OnPropertyChanged("CurrentPageViewModel");
                }
            }
        }

        #endregion

        #region Methods

        private void ChangeViewModel(IPageViewModel viewModel)
        {
            if (!PageViewModels.Contains(viewModel))
                PageViewModels.Add(viewModel);

            CurrentPageViewModel = PageViewModels
                .FirstOrDefault(vm => vm == viewModel);
        }

        #endregion
    }

This won’t compile right away because I’ve made some changes to it. For one, all my PageViewModels now inherit from an IPageViewModel interface so they can have some common properties, such as a Name.

I also created a new HomeViewModel and HomeView since its hard to demonstrate navigation unless you have at least 2 pages. The HomeViewModel is a blank class that inherits from IPageViewModel, and the HomeView is just a blank UserControl.

In addition, I added an s to ProductsViewModel since it really deals with multiple products, not a single one.

An added advantage to having a ViewModel to control the application state is that it can also be used to handle other application-wide objects, such as Current User, or Error Messages.

The View

I also need an ApplicationView for my ApplicationViewModel. It needs to contain some kind of Navigation that shows the list of PageViewModels, and clicking on a PageViewModel should execute the ChangePage command.

It also needs to contain a control to display the CurrentPage property, and I usually use a ContentControl for that. This allows me to use DataTemplates to tell WPF how to draw each IPageViewModel.

<Window x:Class="SimpleMVVMExample.ApplicationView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SimpleMVVMExample"
        Title="Simple MVVM Example" Height="350" Width="525">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:HomeViewModel}">
            <local:HomeView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ProductsViewModel}">
            <local:ProductsView />
        </DataTemplate>
    </Window.Resources>

    <DockPanel>
        <Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
            <ItemsControl ItemsSource="{Binding PageViewModels}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Content="{Binding Name}"
                                Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                CommandParameter="{Binding }"
                                Margin="2,5"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>

        <ContentControl Content="{Binding CurrentPageViewModel}" />
    </DockPanel>
</Window>

In this example, I’m using an ItemsControl to display my PageViewModels. Each item is drawn using a Button, and the Button’s Command property is bound to the ChangePageCommand.

Since the Button’s DataContext is the PageViewModel, I used a RelativeSource binding to find the ChangePageCommand. I know that my Window is the ApplicationView, and it’s DataContext is the ApplicationViewModel, so this binding looks up the VisualTree for the Window tag, and gets bound to Window.DataContext.ChangePageCommand.

Also note that I am putting DataTemplates in Window.Resources to tell WPF how to draw each IPageViewModel. By default, if WPF encounters an object in it’s visual tree that it doesn’t know how to handle, it will draw it using a TextBlock containing the .ToString() method of the object. By defining a DataTemplate, I am telling WPF to use a specific template instead of defaulting to a TextBlock.

If you are continuing from the Simple MVVM Example, I moved the ProductView out of a ResourceDictionary and into a UserControl to make this simpler.

Starting the Example

The last thing to do is change App.xaml to make ApplicationView and ApplicationViewModel our startup, instead of ProductView/ProductViewModel.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        ApplicationView app = new ApplicationView();
        ApplicationViewModel context = new ApplicationViewModel();
        app.DataContext = context;
        app.Show();
    }
}

Run the project and you should see something that looks like the images below, which quickly switches the CurrentPage when clicking on the Navigation buttons.

Screenshot of HomeHome

Screenshot of ProductsProducts

Summary

And there you have it. A simple navigation example with MVVM.

You can download the source code for this sample from here.

Once you get more comfortable with WPF, I would recommend looking into using a Messaging System, such as MVVM Light’s Messenger, or Microsoft Prism’s EventAggregator to broadcast ChangePage commands from any ViewModel so you wouldn’t need to find the ApplicationViewModel to execute the ChangePageCommand, however that’s for another day.

<< Back – A Simple MVVM Example
>> Next – Communication between ViewModels


How a VirtualizingStackPanel works

November 5, 2011

A VirtualizingStackPanel is recommended instead of a regular StackPanel when you have a large number of scrollable items.

The reason for this is that a regular scrolling StackPanel will render every single UI element in the list when its loaded, including the ones that are not visible, while a VirtualizingStackPanel will only render the visible UI elements. When you scroll a VirtualizingStackPanel it will re-use the existing elements instead of creating new ones, and simply replaces the DataContext behind them.

For example, if you have an VirtualizingStackPanel with 100,000 items, and only 10 are visible at a time, it will render about 14 items (extra items for a scroll buffer). When you scroll, the DataContext behind those 14 controls gets changed, but the actual controls themselves will never get replaced. In contrast, a regular StackPanel would actually render 100,000 items when it gets loaded, which would dramatically decrease the performance of your application.

To see a VirtualizingStackPanel in action, create one that has a bunch of TextBoxes that are not bound to anything. If you type Text in TextBox #1, and that TextBox.Text is not bound to anything, then the Text will stay in the top TextBox when you scroll the list because the control is getting re-used. If you bind TextBox.Text to a value, then the DataContext will change when you scroll, which will replace the displayed Text.


WPF ItemsControl Example

September 17, 2011

I recently wanted to lookup some ItemsControl examples, and was was quite surprised that my good friend Google was unable to find me any good sites.

So here’s some quick examples using an ItemsControl.

Basic ItemsControl

The basic ItemsControl syntax will look like this:

<ItemsControl ItemsSource="{Binding MyCollection}" />

By default, this will create a Vertical StackPanel, then it will loop through each item in MyCollection, add it to a TextBlock, then add that TextBox to the StackPanel.

Here’s a screenshot of the UI objects that get created, identified with Snoop

The ItemTemplate

Quite often you don’t want to simply display an item as a TextBlock, and that’s where the ItemTemplate comes in.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding }" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

In this example, I simply changed the TextBlock to a Button, so now when it draws the StackPanel it will draw each item using a Button instead of a TextBlock.

A button is a simple example, however your DataTemplates can be (and frequently are) far more complex than a single element.

The ItemsPanelTemplate

Now suppose you want to display your items in something other than a Vertical StackPanel. That’s where the ItemsPanelTemplate comes in.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="2" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemTemplate -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding }" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

In this case, I’ve replaced our StackPanel with a UniformGrid that has 2 Columns

The ItemContainerStyle

The ItemContainerStyle can be used to modify the style of all items in the ItemsControl, however it does not apply this style to the ItemTemplate item, but rather the ContentPresenter that wraps each item (See Snoop Screenshot above)

For example, if I had used a Grid instead of a UniformGrid, and added a Grid.Row and Grid.Column bindings to my Button, you would find that the items do not show up in the correct Grid cell. If I wanted to set each item in the correct Grid cell, I would need to use the ItemContainerStyle to style the ContentPresenter that wraps each item.

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>

    <!-- ItemTemplate -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding Name}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Note: For all the screenshots above I was binding to an ObservableCollection of strings, however for the last one I created a custom class that had 3 properties: Name, ColumnIndex, and RowIndex


ComboBox’s SelectedItem not Displaying

August 20, 2011

I see a lot of posts on StackOverflow about WPF ComboBoxes not displaying the SelectedItem correctly.

The code given usually looks something like this:

<ComboBox ItemsSource="{Binding MyList}"
          SelectedItem="{Binding MyItem}" />

The problem is simple: By default WPF compares SelectedItem to each item in the ItemsSource by reference, meaning that unless the SelectedItem points to the same item in memory as the ItemsSource item, it will decide that the item doesn’t exist in the ItemsSource and so no item gets selected.

To work around this, you can either use the ComboBox’s SelectedValue and SelectedValuePath to set the SelectedItem by Value instead of by Item

<ComboBox ItemsSource="{Binding MyList}"
          SelectedValuePath="Id"
          SelectedValue="{Binding SelectedId}" />

Or you can overwrite the .Equals() method of the MyItem class so that it returns true if two item’s have the same data, not just the same memory reference.

public override bool Equals(object obj) 
{ 
    if (obj == null || !(obj is MyClass)) 
        return false; 
 
    return ((MyClass)obj).Id == this.Id); 
}

Navigation with MVVM

July 17, 2011

NOTE: I have re-written this article here to provide a better example, and some code samples.


When I first started out with MVVM, I was lost about how you should navigate between pages. I’m a firm believer in using ViewModels to do everything (unless it’s View-specific code), and that the UI is simply a user-friendly interface for your ViewModels. I did not want to create a button on a page that has any kind of code-behind to switch pages, and I didn’t like the idea of my navigation being spread out throughout all the ViewModels.

I finally came to realize the solution was simple: I needed a ViewModel for the Application itself, which contained the application state, such as the CurrentPage.

The ViewModel

Usually I name the ViewModel ShellViewModel or AppViewModel, but you can call it whatever you want. It is the startup page or window in the application, and is usually the only page/window object in my project.

It looks something like this:

    public class ShellViewModel : INotifyPropertyChanged
    {
        private ICommand _changeViewModelCommand;

        private object _currentViewModel;
        private List<object> _viewModels = new List<object>();

        public ShellViewModel()
        {
            ViewModels.Add(new HomeViewModel());
            CurrentViewModel = ViewModels[0];
        }

        private void ChangeViewModel(object viewModel)
        {
            if (!ViewModels.Contains(viewModel))
                ViewModels.Add(viewModel);

            CurrentViewModel = ViewModels.FirstOrDefault(vm => vm == viewModel);
        }
    }

I have omitted the public property implementation and the INotifyPropertyChanged interface methods for sake of readability. The public properties are your standard get/set properties that raise a PropertyChange notification, and the public ChangeViewModelCommand points to the ChangeViewModel method.

The View

I also need a ShellView for my ShellViewModel, so this is what it usually looks like:

<Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Header -->
        <TextBlock Text="Application Name" FontWeight="Bold" FontSize="24" />

        <Line Grid.Row="1" Stroke="Black" Margin="0,5" StrokeThickness="1" Stretch="Fill" X2="1" />        <!-- Content -->
        <ContentControl Grid.Row="2" Content="{Binding CurrentViewModel}"/>
</Grid>

It contains a standard frame for the application, in this case the application name with a horizontal line under it, followed by the CurrentPage in a ContentControl. When a page is displayed in the ContentControl, WPF will lookup the appropriate DataTemplate to use to display that ViewModel (page).

Changing Pages

The ChangePage command can either be called directly through the XAML using something like this:

<Button Command="{Binding RelativeSource={RelativeSource
            AncestorType={x:Type Window}},
            Path=DataContext.ChangeViewModelCommand}
        CommandParameter="{Binding EditCustomerViewModel}"
        />

or you can use an Event system such as PRISM’s EventAggregator or MVVM Light’s Messenger, and the ViewModels would raise a ChangePage event. I prefer to use an Event system personally, but use whatever works for you.

For more on switching between Pages/Views, see this article


Communication between ViewModels with MVVM

June 5, 2011

Communication between ViewModels can be tricky at first glance, but there are some easy frameworks and patterns that can help you out.

For example, lets say you had a ShellViewModel that controlled your entire application, and it has an Exit command. Now lets say one of the sub-view-models in the application would like to call this exit command.

The easiest way is through a Relative Binding to the Window’s DataContext.ExitCommand.

<Button Command="{Binding 
    RelativeSource={RelativeSource AncestorType={x:Type Window},
    Path=DataContext.ExitCommand}}

Of course, this only works well if you can find the control containing the command you want through a binding.

Enter the Event System

Another way is through a loosely coupled event system. I would recommend either MVVM Light’s Messenger or Microsoft Prism’s EventAggregator. You could always build your own event system as well if you really wanted to.

Both event systems makes me think of a paging system. Any ViewModel can broadcast a message, and any ViewModel can subscribe to receive broadcasted messages. Messages are often packaged into different types, so a ViewModel can subscribe to only listen for specific message types such as CloseApplicationMessages.

This kind of loosely coupled event system is ideal for MVVM because the ViewModels don’t need to know about each other to be able to do their job.

Using either of these systems, your ViewModel that handles the event would subscribe to receive a specific message type. It would tell the event system that if a message of type X is broadcasted, send it to a specified delegate method. The ViewModel that wishes to raise the event simply has to broadcast the message and include any parameters needed in the body of the message.

Example using Prism’s EventAggregator

// Subscribe
eventAggregator.GetEvent<CloseAppliactionMessage>().Subscribe(ExitMethod);

// Broadcast
eventAggregator.GetEvent<CloseAppliactionMessage>().Publish();

(I also have some code posted here which simplifies PRISM’s EventAggregator for smaller applications)

Example using MVVM Light’s Messenger

//Subscribe
Messenger.Default.Register<CloseAppliactionMessage>(ExitMethod);

// Broadcast
Messenger.Default.Send<CloseAppliactionMessage>()

Switching between Views/UserControls using MVVM

May 28, 2011

I often like to browse questions tagged with WPF or MVVM on StackOverflow, and one question I see come up frequently is how to switch between Views or UserControls in MVVM.

Once you get used to the fact that the ViewModels run your application, it is very simple. Your ViewModel contains a property which defines your CurrentView and to switch views you simply switch your ViewModel’s properties.

There is more than one way to do this, but I’ll show  two common examples.

Using a DataTemplate

The simplest way is to use a DataTemplate. Lets say you have a window with two screens you want to switch between: Home and Work. You have a Menu at the top with two options: View Home Page and View Work Page. Your ViewModel behind this page would have a CurrentView property, along with two commands: ViewHomeCommand and ViewWorkCommand.

public class AppViewModel
{
    // simplified properties
    public ViewModelBase CurrentView {get; set;}
    public ICommand ViewHomeCommand {get;}
    public ICommand ViewWorkCommand {get;}
}

The page’s content would simply be a ContentControl with it’s content bound to CurrentView.

<ContentControl Content="{Binding CurrentView}" />

Now all you need to do is define two DataTemplates, one for the Home and one for the Work

<DataTemplate DataType="{x:Type HomeViewModel}">
    <TextBlock Text="This is the Home Page" />
</DataTemplate>
<DataTemplate DataType="{x:Type WorkViewModel}">
    <localControls:WorkViewUserControl />
</DataTemplate>

When you execute ViewHome/Work commands, all it is doing is setting the CurrentView to an instance of either HomeViewModel, or WorkViewModel. That ViewModel is getting bound to the ContentControl, and the DataTemplate is used to determine how to display the object.

Using a DataTrigger

Sometimes you may want to switch views based on a property instead of a type. Lets say you’re viewing a list of Consumers, and you want to display one View if the consumer is a Business, and a different View if the Consumer is a Person. In this case, you would use a DataTrigger

<DataTemplate x:Key="PersonTemplate" DataType="{x:Type local:ConsumerViewModel}">
     <TextBlock Text="I'm a Person" />
</DataTemplate> 

<DataTemplate x:Key="BusinessTemplate" DataType="{x:Type local:ConsumerViewModel}">
     <TextBlock Text="I'm a Business" />
 </DataTemplate>

<DataTemplate DataType="{x:Type local:ConsumerViewModel}">
     <ContentControl Content="{Binding }">
         <ContentControl.Style>
             <Style TargetType="{x:Type ContentControl}">
                 <Setter Property="ContentTemplate" Value="{StaticResource PersonTemplate}" />
                 <Style.Triggers>
                     <DataTrigger Binding="{Binding ConsumerType}" Value="Business">
                         <Setter Property="ContentTemplate" Value="{StaticResource BusinessTemplate}" />
                     </DataTrigger>
                 </Style.Triggers>
             </Style>
         </ContentControl.Style>
     </ContentControl>
 </DataTemplate>

Here we have a DataTemplate for a Consumer object which defaults to the PersonTemplate. In a DataTrigger, it checks to see if the ConsumerType is a Business and if so switches to a BusinessTemplate. All you have left to do is bind the Consumer object to a ContentControl to display it.

<ContentControl Content="{Binding CurrentConsumer}" />

Summary

Switching between views using MVVM isn’t hard at all. You just need to remember that the ViewModel is driving the application, not the View. The way I see it, your application should be able to run through a command-line interface, so everything your application needs to know about its state should be in the ViewModels somewhere. This includes the current view.


Tricking EF to span Multiple Databases

May 22, 2011

I was working on a project recently that used Entity Framework and had to span multiple databases. I was quite surprised to find out that EF didn’t support making one edmx file span multiple databases, and so came up with this solution to get around that using SQL Synonyms.

Here’s a quick walkthrough of how it works. Lets say I have two databases, located on separate servers. We’ll call them ServerA.DatabaseA and ServerB.DatabaseB. I would like to have one edmx file that contains objects from both databases, and include links between the two.

Setting up the Synonyms

First, I needed to setup my database synonyms. A simple script like this was run on DatabaseB to print out my CREATE SYNONYM statements, and the resulting output got verified and ran on DatabaseA.

declare @name varchar(max)

DECLARE db_cursor CURSOR FOR
select name from sysobjects where type = 'U'

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @name   

WHILE @@FETCH_STATUS = 0
BEGIN   

print 'CREATE SYNONYM [dbo].[' + @name + '] FOR [ServerB].[DatabaseB].[dbo].[' + @name + ']
 '
       FETCH NEXT FROM db_cursor INTO @name
END   

CLOSE db_cursor
DEALLOCATE db_cursor

This allowed me to reference tables on ServerB.DatabaseB from ServerA.DatabaseA using their regular table names. For example, if DatabaseA had Customers and DatabaseB had products, this allows me to run

SELECT * FROM Products

from DatabaseA instead of writing

SELECT * FROM ServerB.DatabaseB.dbo.Products

It will also work on Views, Stored Procedures, and User-Defined Functions. The only catch is no two object names can be the same.

Creating the EDMX files

Next, we need to create our edmx files. You will end up with one working copy of the edmx file, and a separate copy for each database you are trying to span.

Create a project for each database containing nothing more than a single edmx file pointing to one of the databases. Name the edmx files the same and make sure the entity namespaces are the same.

Now create a 3rd project and edmx file for your working copy. Make sure it’s also named the same and has the same entity namespace. Point it to whatever database contains the synonyms. In this case, that’s DatabaseA.

Merging the edmx files

Now we need to merge the edmx files. Since they are just xml files, this could be done by hand, but if we did that we’d need to do it every time the database got updated, so a script is far better.

Here is the one I use. Its not perfect, but for an XML dummy like me it worked just fine. I created a new project to hold it, and whenever I made changes to my edmx files I would run this project.

static void Main(string[] args)
{
    // Directory that can access all 3 edmx files
    // Fairly sure there's a better way to do this, but this
    // was the first that came to my mind
    string rootDir = Directory.GetCurrentDirectory() + @"..\..\..\..\";

    // Location of working edmx file to write merged edmx to
    string resultFile = rootDir + @"DAL\Entities.edmx";

    // List of edmx files to merge
    string[] files = new string[]
    {
        rootDir + @"DatabaseA\Entities.edmx",
        rootDir + @"DatabaseB\Entities.edmx"
    };

    // Load result file
    var a = new XmlDocument();
    a.Load(resultFile);

    // TODO: Clear result file of anything except LNK_ items?
    // Actually that might cause a problem with nav properties.
    // Will probably have to create a merged file of list of files,
    // then merge changes from that single file with the result file

    // Loop through files to merge and add their nodes to the result file
    foreach (var edmxFile in files)
    {
        var b = new XmlDocument();
        b.Load(edmxFile);

        string rootNode = "/edmx:Edmx/edmx:Runtime/";

        XmlNamespaceManager nsMan = new XmlNamespaceManager(a.NameTable);
        nsMan.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");

        // SSDL
        MergeNodes(
            a.SelectSingleNode(rootNode + "edmx:StorageModels", nsMan)["Schema"]["EntityContainer"],
            b.SelectSingleNode(rootNode + "edmx:StorageModels", nsMan)["Schema"]["EntityContainer"].ChildNodes,
            a, b);

        MergeNodes(
            a.SelectSingleNode(rootNode + "edmx:StorageModels", nsMan)["Schema"],
            b.SelectSingleNode(rootNode + "edmx:StorageModels", nsMan)["Schema"].ChildNodes,
            a, b);

        // CSDL
        MergeNodes(
            a.SelectSingleNode(rootNode + "edmx:ConceptualModels", nsMan)["Schema"]["EntityContainer"],
            b.SelectSingleNode(rootNode + "edmx:ConceptualModels", nsMan)["Schema"]["EntityContainer"].ChildNodes,
            a, b);

        MergeNodes(
            a.SelectSingleNode(rootNode + "edmx:ConceptualModels", nsMan)["Schema"],
            b.SelectSingleNode(rootNode + "edmx:ConceptualModels", nsMan)["Schema"].ChildNodes,
            a, b);

        // MSL
        MergeNodes(
            a.SelectSingleNode(rootNode + "edmx:Mappings", nsMan)["Mapping"]["EntityContainerMapping"],
            b.SelectSingleNode(rootNode + "edmx:Mappings", nsMan)["Mapping"]["EntityContainerMapping"].ChildNodes,
            a, b);

    }

    // Save result file
    a.Save(resultFile);

    Console.WriteLine("Done");
    Console.ReadLine();
}

private static void MergeNodes(XmlNode parentNodeA, XmlNodeList childNodesB, XmlDocument parentA, XmlDocument parentB)
{
    foreach (XmlNode oNode in childNodesB)
    {
        // Exclude container node and comments
        if (oNode.Name == "EntityContainer" || oNode.Name == "#comment") continue;

        bool isFound = false;
        string name = oNode.Attributes["Name"].Value;

        foreach (XmlNode child in parentNodeA.ChildNodes)
        {
            if (child.Name == "EntityContainer" || child.Name == "#comment") continue;

            // If node already exists, exit loop
            if (child.OuterXml == oNode.OuterXml && child.InnerXml == oNode.InnerXml)
            {
                isFound = true;
                Console.WriteLine("Found::NoChanges::" + oNode.Name + "::" + name);
                break;
            }

            // If node by the same name exists
            if (child.Attributes["Name"].Value == name)
            {
                if (oNode.Name == "EntityType")
                {
                    foreach (XmlNode property in child.ChildNodes)
                    {
                        // Make sure to keep any navigation properties that have been added
                        if (property.Name == "NavigationProperty"
                            && property.Attributes["Relationship"] != null
                            && Regex.IsMatch(property.Attributes["Relationship"].Value, @".*\.LNK_.*"))
                        {
                            oNode.AppendChild(parentB.ImportNode(property, true));
                        }
                    }
                }

                isFound = true;
                Console.WriteLine("Found::Replaced::" + oNode.Name + "::" + name);
                parentNodeA.ReplaceChild(parentA.ImportNode(oNode, true), child);
            }
        }        if (!isFound)
        {
            Console.WriteLine("NotFound::Adding::" + oNode.Name + "::" + name);
            parentNodeA.AppendChild(parentA.ImportNode(oNode, true));
        }
    }}

This is a work in progress, but it works for now. I’ll update this post after I fix up the merge project.

Creating Links between the Databases

Now you’ll have one edmx file, containing the information from both databases. You can create Associations between the two objects, however they will be erased anytime you merge your changes. To get around this, make sure all your links contain the same prefix and modify the merge code to exclude NavigationProperties that are prefixed with whatever you use. In my case, I prefixed them with LNK_

Summary

And there you have it. Test it out and you’ll find it works just fine. Your working edmx points to DatabaseA, which contains synonyms for DatabaseB objects. EF has no idea that half its objects exist on another database, because from its point of view it is all one database. Navigational properties between the two databases work just fine providing you’ve manually setup the links in the working copy.

To update the working copy, update the projects containing the individual database edmx, and run the merge code again. Providing you don’t make any changes to the working copy except links, and all your links contain the same prefix to avoid getting erased when the merge occurs, you should have no problems.

Screenshot of MergeEdmx Projects

Notes

  • This only works in a databases that supports Synonyms. I was using SQL Server 2005.
  • This was the first project I did using EF and I was using EF 4. I have no idea if this works on older versions.
  • You have to be sure that items are uniquely named between databases.
  • The Merge code is not perfect – sorry. I plan on fixing it up to remove Deleted items but haven’t gotten around to it. I just have a TODO bit in my code for now. If someone knows of a better tool to merge XML files, let me know! It has to be something an xml-idiot can use though 🙂