7

Can someone point to an example of how to programmatically create & use Radio Buttons in C# WPF?

So basically how to (a) create them programmatically, and (b) how to catch triggers when the value changes, (c) how to pick up results at a given time.

Will be interested to see too if the answer will be based on use of a Binding approach too. If data binding is the easiest way to go then an example of this would be great. Else if data binding isn't necessary the best/easiest way to go then a non-data-binding based example would be good.

Notes:

  • Note that the parent node I have currently is StackPanel, so an aspect of the question is how to add multiple RadioButtons to a StackPanelI guess.

  • Should point out that I won't know how many radio buttons there will be at compile time, nor what the text will be this will be discovered at run time.

  • It is a WPF application (i.e. desktop, not a web app)

1 Answer 1

16

Normally, we use RadioButtons to present an Enum data type to the user. And what we usually do is use an ItemsControl to present a group of RadioButtons, with each one bound to a ViewModel.

Below is a sample application I just wrote that demonstrates how RadioButtons could be used in two ways: the first is somewhat of a direct approach (and this may answer your questions above), and the second one uses an MVVM approach.

BTW, this is just something I wrote quickly (yeah, I got a lot of time in my hands) so I won't say that everything in here is the perfect way of doing things. But I hope you find this helpful:

XAML:

<Window x:Class="RadioButtonSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:RadioButtonSample"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel x:Name="sp"/>
        <Button x:Name="showChoice" Click="showChoice_Click">Show Choice</Button>

        <StackPanel x:Name="sp2">
            <StackPanel.DataContext>
                <local:ViewModel/>
            </StackPanel.DataContext>
            <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Path=Choices}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <RadioButton IsChecked="{Binding Path=IsChecked}" Content="{Binding Path=Choice}" GroupName="ChoicesGroup"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        <Button x:Name="showChoice2" Click="showChoice2_Click">Show Choice2</Button>
    </StackPanel>
</StackPanel>

Code-behind:

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.Generic;

namespace RadioButtonSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //Initialize the first group of radio buttons and add them to the panel.
            foreach (object obj in Enum.GetValues(typeof(ChoicesEnum)))
            {
                RadioButton rb = new RadioButton() { Content = obj, };
                sp.Children.Add(rb);
                rb.Checked += new RoutedEventHandler(rb_Checked);
                rb.Unchecked += new RoutedEventHandler(rb_Unchecked);
            }
        }

        void rb_Unchecked(object sender, RoutedEventArgs e)
        {
            Console.Write((sender as RadioButton).Content.ToString() + " checked.");
        }

        void rb_Checked(object sender, RoutedEventArgs e)
        {
            Console.Write((sender as RadioButton).Content.ToString() + " unchecked.");
        }

        private void showChoice_Click(object sender, RoutedEventArgs e)
        {
            foreach (RadioButton rb in sp.Children)
            {
                if (rb.IsChecked == true)
                {
                    MessageBox.Show(rb.Content.ToString());
                    break;
                }
            }
        }

        private void showChoice2_Click(object sender, RoutedEventArgs e)
        {
            //Show selected choice in the ViewModel.
            ChoiceVM selected = (sp2.DataContext as ViewModel).SelectedChoiceVM;
            if (selected != null)
                MessageBox.Show(selected.Choice.ToString());
        }
    }

    //Test Enum
    public enum ChoicesEnum
    {
        Choice1,
        Choice2,
        Choice3,
    }

    //ViewModel for a single Choice
    public class ChoiceVM : INotifyPropertyChanged
    {
        public ChoicesEnum Choice { get; private set; }
        public ChoiceVM(ChoicesEnum choice)
        {
            this.Choice = choice;
        }

        private bool isChecked;
        public bool IsChecked
        {
            get { return this.isChecked; }
            set
            {
                this.isChecked = value;
                this.OnPropertyChanged("IsChecked");
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        #endregion

    }

    //Sample ViewModel containing a list of choices
    //and exposes a property showing the currently selected choice
    public class ViewModel : INotifyPropertyChanged
    {
        public List<ChoiceVM> Choices { get; private set; }
        public ViewModel()
        {
            this.Choices = new List<ChoiceVM>();

            //wrap each choice in a ChoiceVM and add it to the list.
            foreach (var choice in Enum.GetValues(typeof(ChoicesEnum)))
                this.Choices.Add(new ChoiceVM((ChoicesEnum)choice));
        }

        public ChoiceVM SelectedChoiceVM
        {
            get
            {
                ChoiceVM selectedChoice = this.Choices.FirstOrDefault((c) => c.IsChecked == true);
                return selectedChoice;
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        #endregion

    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

thanks - in my case I won't know the number of radio buttons at compile time, hence I'm not sure about the enum approach - any advice re what to do in this case?
I believe it will work the same way. I would think that the items in your group of RadioButtons will be a collection of some sorts. So in the code above, just replace the loops that iterate "Enum.GetValues(...)" to use your collection instead. Hope this makes sense.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.