WPF MVVM project template

This extension will add a Visual Studio 2010 project template to create a WPF client application with MVVM pattern project structure.

(after installing the .vsix you’ll need to restart Visual Studio).

the new project template can be found under: File -> New -> Project -> C# templates.
it is called “WPF MVVM Application”.

the new project have an MVVM folders and classes structure with some randomly generated data and a simple view.

download from HERE

WPF: MenuButton

i was looking for a Menu-Button (some call it Drop-Down-Button) and found this post: DropDownButtons in WPF.
all credits goes to Andy, i’ve just adapted his code and idea.
here is my version:

public class MenuButton : ToggleButton
{
    public enum Placement { Bottom, Right }
    public Placement MenuPlacement { private get; set; }

    #region DropDown (DependencyProperty)

    public ContextMenu Menu
    {
        get { return (ContextMenu)GetValue(MenuProperty); }
        set { SetValue(MenuProperty, value); }
    }
    public static readonly DependencyProperty MenuProperty =
        DependencyProperty.Register("Menu", typeof(ContextMenu), typeof(MenuButton),
            new PropertyMetadata(null, OnMenuChanged)
            );

    private static void OnMenuChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        ((MenuButton)sender).OnMenuChanged(e);
    }

    private void OnMenuChanged(DependencyPropertyChangedEventArgs e)
    {
        if (Menu != null)
        {
            Menu.PlacementTarget = this;

            switch (MenuPlacement)
            {
                default:
                case Placement.Bottom:
                    Menu.Placement = PlacementMode.Bottom;
                    break;
                case Placement.Right:
                    Menu.Placement = PlacementMode.Right;
                    break;
            }

            this.Checked += new RoutedEventHandler((a, b) => { Menu.IsOpen = true; });
            this.Unchecked += new RoutedEventHandler((a, b) => { Menu.IsOpen = false; });
            Menu.Closed += new RoutedEventHandler((a, b) => { this.IsChecked = false; });
        }
    }

    #endregion

    #region MenuSource (DependencyProperty)

    public IEnumerable MenuSource
    {
        get { return (IEnumerable)GetValue(MenuSourceProperty); }
        set { SetValue(MenuSourceProperty, value); }
    }
    public static readonly DependencyProperty MenuSourceProperty =
        DependencyProperty.Register("MenuSource", typeof(IEnumerable), typeof(MenuButton),
            new PropertyMetadata(null, OnMenuSourceChanged)
            );

    private static void OnMenuSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        ((MenuButton)sender).OnMenuSourceChanged(e);
    }

    private void OnMenuSourceChanged(DependencyPropertyChangedEventArgs e)
    {
        if (Menu == null)
            Menu = new ContextMenu();

        Menu.ItemsSource = e.NewValue as IEnumerable;
    }

    #endregion

}

WPF: DataGrid with integrated field (column) chooser

following a discussion in the comments of this post
this is the WPF version of a DataGrid control with integrated columns chooser that opens when right-clicking one of the headers.
(see Silverlight demo)
full source code over here

this is how it look like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace WPF_DataGridWithColumnChooser.Controls
{
    public class DataGridExtended : DataGrid
    {
        public DataGridExtended()
            : base()
        {
            theContextMenu = new ContextMenu();
            this.Columns.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Columns_CollectionChanged);
        }

        private ContextMenu theContextMenu; //context menu for the field chooser.
        private string AllColumnsHeaders { get; set; }
        private bool oneTime = true;

        protected override Size ArrangeOverride(Size finalSize)
        {
            if (oneTime)// do this only once.
            {
                oneTime = false;
                var headersPresenter = FindChild(this);
                // attach the context menu.
                ContextMenuService.SetContextMenu(headersPresenter, theContextMenu);

                // update VisibleColumns as necessary.
                if (String.IsNullOrEmpty(VisibleColumns))
                {
                    VisibleColumns = AllColumnsHeaders;
                }
                else
                {
                    string s = VisibleColumns;
                    VisibleColumns = null;
                    VisibleColumns = s;
                }
            }
            return base.ArrangeOverride(finalSize);
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem mi = sender as MenuItem;
            Image icon = (Image)mi.Icon;
            List splited = VisibleColumns.Split(';').ToList();
            string colName = mi.Header.ToString();

            // remove empty items.
            for (int i = 0; i  1)
                {
                    splited.Remove(colName);
                }
            }

            // update the VisibleColumns.
            string build = "";
            foreach (string name in splited)
            {
                build = string.Format("{0};{1}", name, build);
            }
            VisibleColumns = build;
        }

        private void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

            DataGridColumn col = e.NewItems[0] as DataGridColumn;

            // keep a list of all clomuns headers for later use.
            AllColumnsHeaders = String.Format("{0};{1}", col.Header.ToString(), AllColumnsHeaders);

            // make a new menu item and add it to the context menu.
            MenuItem menuItem = new MenuItem();
            Image img;
            menuItem.Click += new RoutedEventHandler(MenuItem_Click);
            menuItem.Header = col.Header.ToString();
            img = new Image();
            img.Source = Application.Current.Resources["Vmark"] as ImageSource;
            menuItem.Icon = img;
            theContextMenu.Items.Add(menuItem);

        }

        #region VisibleColumns (DependencyProperty)

        /// <summary>
        /// Gets or sets a value indicating the names of columns (as they appear in the column header) to be visible, seperated by a semicolon.
        /// columns that whose name is not here will be hidden.
        /// </summary>
        public string VisibleColumns
        {
            get { return (string)GetValue(VisibleColumnsProperty); }
            set { SetValue(VisibleColumnsProperty, value); }
        }

        public static readonly DependencyProperty VisibleColumnsProperty =
            DependencyProperty.Register(
                "VisibleColumns",
                typeof(string),
                typeof(DataGridExtended),
                new PropertyMetadata("", new PropertyChangedCallback(OnVisibleColumnsChanged))
                );

        private static void OnVisibleColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataGridExtended dg = (DataGridExtended)d;
            dg.VisibleColumnsChanged(e);

        }

        private void VisibleColumnsChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
            {
                string[] showTheseColumns = e.NewValue.ToString().Split(';');
                string colName;

                // update the columns visibility.
                foreach (DataGridColumn col in this.Columns)
                {
                    colName = col.Header.ToString();

                    if (showTheseColumns.Contains(colName))
                        col.Visibility = Visibility.Visible;
                    else
                        col.Visibility = Visibility.Collapsed;
                }

                // update the context menu items.
                if (theContextMenu != null)
                {
                    foreach (MenuItem menuItem in theContextMenu.Items)
                    {
                        colName = menuItem.Header.ToString();
                        if (showTheseColumns.Contains(colName))
                            ((Image)menuItem.Icon).Visibility = Visibility.Visible;
                        else
                            ((Image)menuItem.Icon).Visibility = Visibility.Collapsed;
                    }
                }
            }
        }

        #endregion

        public static T FindChild(DependencyObject depObj) where T : DependencyObject
        {
            // Confirm obj is valid.
            if (depObj == null) return null;

            // success case
            if (depObj is T)
                return depObj as T;

            for (int i = 0; i &lt; VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

                T obj = FindChild(child);

                if (obj != null)
                    return obj;
            }

            return null;
        }
    }

}
Follow

Get every new post delivered to your Inbox.