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

Advertisements

Resource Viewer V2.0

Version 2.0 is out!

Read the first post and full description: Resource Viewer – A Visual Studio Extension

New in V2.0:

  • Added support for additional resource types – now you can also view your Brush(es):DrwaingBrush,  SolidColorBrush, Gradients, etc.
  • Details view.
  • The code is now constructed better.

The whole project and source code is maintained here: http://resourceviewer.codeplex.com/

It is also hosted in the Visual Studio gallery, here: Resource Viewer

Resource Viewer – A Visual Studio Extension

Simply put the “resource viewer extension” enables you to visually view your ResourceDictionary.

To open it go to: View – Other Windows – Resource Viewer.

When working with WPF/Silverlight you put your reusable resources in a common ResourceDictionary, those resources might be of type Style, SolidColorBrush, DrawingBrush, BitmapImage and more. The problems starts when you have that ResourceDictionary you have no way to see how your resources look like, making the work process (of both the developer who maintains this dictionary and the one who uses it) clumsy and based on guessing.

This extension comes to solve those problems!

With the “Resource viewer “ extension you can open any ResourceDictionary and actually see how your resources look like – your icons, brushes, etc. are all being visualized right inside Visual Studio.

Than when you’ve found the resource you’ve been after you can “inject” it into a file that is opened within Visual Studio.

Features:

  • A Visual Studio 2010 extension – meaning it integrates with VS api and behave like any other window (docking, floating etc.)
  • Open any XAML ResourceDictionary file on your computer – simply browse to it.
  • When you open the viewer it automatically opens the last opened file.
  • Most recently used files list.
  • Refresh button to reload the opened file.
  • The opened file is being watched for changes, if a change is made you’ll be notified.
  • Zoom slider and zoom presets.
  • Search box.
  • Inject the selected item’s x:Key into an opened document by double-click on an item or pressing the “Inject” button.
  • Inject prefix and suffix strings. Those are saved and persisted.

Future plans:

  • Current version handles only DrawingImage, add handling for more resource types.
  • Add handling for Merged Dictionaries.
  • Add a detailed view for the selected item.
  • More…

If you are willing to help in any way please drop me a note.

The whole project and source code is maintained here: http://resourceviewer.codeplex.com/

It is also hosted in the Visual Studio gallery, here: Resource Viewer

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;
        }
    }

}