Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF MVVM Binding for Multiple Radio Buttons

0.00/5 (No votes)
12 Aug 2014 1  
WPF MVVM Binding for Multiple Radio Buttons and Win 8 Metro Theme

Introduction

This article demonstrates the following key features: 

A MVVM pattern to handle and manipulate a collection of Radio Buttons.

Stable solution for the IsChecked property without having to usine groups and convertors.

Implicitly set the theme of the project to a windows 8 Metro styled theme for Windows 7 and 8 using MahApps (You will find this .dll file in the packages folder in the source attached to this article.) MahApps web site: http://mahapps.com/

How to segregate views from code in seperate projects. The main reason to do this is if you are going to obfuscate your source you want to keep XAML file seperate as they do not obfuscate correctly.

Creation of a generic reusuable Commands .dll

Background

I am creating this article, because when I was looking for a similar concept i struggled and saw a lot of people were creating their own convertors and basically seemed like a very heavy and tacky approach to handling the same selected functionality as WinForms offers for Radio Buttons.

My approach  is less reliant on C# code to handle the single selection of Radio Buttons basically besides your View Model for setting your multiple Radio Button source and selected object to handle whatever purpose you may need my example does not require much code and rather lets the XAML handle the tedious work.

I use a ListBox control to handle the logic so I can them just bind the IsChecked to the parent's IsSelected property that way you can only have a single selected object at a time.

<ListBox ItemsSource="{Binding RadioCollection}" SelectedItem="{Binding SelectedRadio}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <RadioButton 
                                    Content="{Binding Header}" ToolTip="{Binding ToolTip}"
                                    IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected}"/>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Margin" Value="5"/>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>

This is an extemely basic project and will give you the good foundation to build up on.

Using the code

Implicitly setting the theme is pretty simple in your App.xaml file add the following MergedDictionaries after referencing the MahApps.dll, there are few accents you can set for example to mention a few: Red, Green, Blue, and Orange. There are also two themes you can set either: BaseDark or BaseLight.

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

Adding the following attribute inside the opening Window tag

xmlns:con="http://metro.mahapps.com/winfx/xaml/controls"

Now you set your Window tag to con:MetroWindow and then do the same on the code behind. Your code behind on the end product if you are using the MVVM pattern should always look like the following

using MahApps.Metro.Controls;
using System;
using System.Linq;

namespace RadioButtonClient

{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Do not set DataContext for window in code behind rather add an attribute to you window tag and then set the DataContext in the XAML

// Attribute tag

xmlns:vm="clr-namespace:RadioButtonCommon;assembly=RadioButtonCommon"

// DataContext

<con:MetroWindow.DataContext>
        <vm:RadioControlVM/>
    </con:MetroWindow.DataContext>

Your ViewModelBase should be the PropertyChangedEventHandler for the entire solution

public abstract class ViewModelBase : INotifyPropertyChanged
    {
        #region Implementing PropertyChangedEventHandler
        public event PropertyChangedEventHandler PropertyChanged;

        public void SetPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion Implementing PropertyChangedEventHandler
    }

Create a basic model for the properties you would want your selected Radio Button to have my example just has a Header and ToolTip

public class RadioModel : ViewModelBase
    {
        #region Header
        private string header = string.Empty;
        public string Header
        {
            get { return header; }
            set
            {
                if (value != this.header)
                    header = value;
                this.SetPropertyChanged("Header");
            }
        }
        #endregion Header
        #region ToolTip
        private string tooltip = string.Empty;
        public string ToolTip
        {
            get { return tooltip; }
            set
            {
                if (value != this.tooltip)
                    tooltip = value;
                this.SetPropertyChanged("ToolTip");
            }
        }
        #endregion ToolTip
        #region String Override
        public override string ToString()
        {
            string returnString = string.Empty;
            if (!string.IsNullOrEmpty(this.header))
                returnString = "Radio button header: {0}. Tooltip: {1}".FormatString(this.header, this.tooltip);
            else returnString = "Not set...";
            return returnString;
        }
        #endregion String Override
    }

I am not going to go into detail on the ViewModel for this article as you can go through it in the attached source code.

History

First Draft: 2014/08/13

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here