Click here to Skip to main content
15,883,814 members
Articles / Desktop Programming / WPF
Tip/Trick

WPF MVVM Binding for Multiple Radio Buttons

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
12 Aug 2014CPOL2 min read 45.1K   1.2K   7   5
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.

C#
<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

C#
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

C#
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

C#
// 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

C#
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

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
South Africa South Africa
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSingle Application Pin
Saffa Shujah10-Dec-14 8:58
Saffa Shujah10-Dec-14 8:58 
GeneralMy vote of 5 Pin
Volynsky Alex27-Aug-14 13:27
professionalVolynsky Alex27-Aug-14 13:27 
Suggestionimage of the result Pin
Nisha Pal14-Aug-14 18:35
Nisha Pal14-Aug-14 18:35 
GeneralRe: image of the result Pin
Jdarmanovich14-Aug-14 22:41
Jdarmanovich14-Aug-14 22:41 
Hi Nisha,

If you download the source you should be able to execute and debug to see the result
QuestionMmmm Pin
Sacha Barber13-Aug-14 2:51
Sacha Barber13-Aug-14 2:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.