StonedJesus
StonedJesus

Reputation: 397

Generate RadioButtons With Different 'Content'

I am a C++ developer and currently working on a WPF app where I have to generate 4 radio buttons dynamically and each button will have different title name. I am following MVVM pattern.

<Grid Grid.Row="0">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="35" />                
        </Grid.RowDefinitions>

        <RadioButton Grid.Row="0" Content="{Binding RadioBase}" IsChecked="{Binding BaseCheck}" Height="15" Width="80" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Center" />
        <Button Grid.Row="1" Content="Refresh Regs" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" Width="100" Height="25" />
</Grid>

Now if you notice my XAMl, I have just One radio button in my Grid.Row="0". Ideally I would want to generate it 4 times and set a binding to its Content and IsChecked so that I gives me 4 different Content.

ViewModel:

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

private string _RadioBase;
    public string RadioBase
    {
        get
        {
            return _RadioBase;
        }

        set
        {
            _RadioBase= value;
            OnPropertyChanged("RadioBase");
        }
    }

I had done this in my C++ application as follows:

for(i = 0; i < 4; i++)
{
    m_registerBase[i] = new ToggleButton(("Base 0x")+String::toHexString(i * 0x40));        
    addAndMakeVisible(m_registerBase[i]);
    m_registerBase[i]->addButtonListener(this);
}

If you notice here, It creates it 4 times and has one buttonclick event. It creates Title as follows:

How can I achieve like this in My WPF application? :) I would appreciate if you guys help me solve this? :)

Thanks

Upvotes: 0

Views: 356

Answers (4)

Mate
Mate

Reputation: 5274

Based on yours comment, I created a complete example :

Model:

    namespace WpfApplication1
    {
        public class RB
        {
            public bool BaseCheck { get; set; }
            public string RadioBase { get; set; }
        }
    }

RBVM:

        namespace WpfApplication1
        {
            public class RBVM : INotifyPropertyChanged
            {

                public RBVM()
                {
                    _rb = new RB();
                }

               private RB _rb;
                public RB RB
               {
                   get
                   {
                       return _rb;
                   }
                   set
                   {
                       _rb = value;
                   }
               }

                public bool BaseCheck
                {
                    get
                    {
                        return RB.BaseCheck;
                    }
                    set
                    {
                        RB.BaseCheck = value;
                        RaisePropertyChanged("BaseCheck");
                    }
                }

                public string RadioBase
                {
                    get
                    {
                        return RB.RadioBase;
                    }
                    set
                    {
                        RB.RadioBase = value;
                        RaisePropertyChanged("RadioBase");
                    }
                }








                public event PropertyChangedEventHandler PropertyChanged;

                                                    #region Methods

            private void RaisePropertyChanged(string propertyName)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            #endregion
            }
        }

ViewModel:

     namespace WpfApplication1
    {
        public class RBViewModel : INotifyPropertyChanged
        {

            public void AddRb(string content, bool isChk) 
            {
                _rbs.Add(new RBVM() { RadioBase = content, BaseCheck = isChk });
            }


            public void ClearAllValues() {
                foreach (RBVM item in _rbs)
                {
                    item.BaseCheck = false;
                }

            }

            public RBVM GetChecked() {
                foreach (RBVM item in _rbs)
                {
                    if (item.BaseCheck) {
                        return item;
                    }
                }

                return null;

            }


            private ObservableCollection<RBVM> _rbs = new ObservableCollection<RBVM>();


            public ObservableCollection<RBVM> Rbs
           {
               get
               {
                   return _rbs;
               }
               set
               {
                   _rbs = value;
               }
           }



            public event PropertyChangedEventHandler PropertyChanged;

            #region Methods

            private void RaisePropertyChanged(string propertyName)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            #endregion
        }
    }

XAML

    <Window x:Class="WpfApplication1.MainWindow1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
            Title="MainWindow1" Height="300" Width="300">

        <Window.DataContext>
            <local:RBViewModel />
        </Window.DataContext>
        <Window.Resources>

            <DataTemplate x:Key="RadioDataTemplate">
                <StackPanel>
                    <RadioButton GroupName="someGroup" Content="{Binding RadioBase}" IsChecked="{Binding BaseCheck}" Height="15" Width="80" HorizontalAlignment="Center" VerticalAlignment="Center" />
                </StackPanel>
            </DataTemplate>

        </Window.Resources>

        <Grid x:Name="main">

            <ItemsControl ItemsSource="{Binding Rbs}" ItemTemplate="{StaticResource RadioDataTemplate}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel x:Name="radios" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>

            <Button Width="50" Height="10" x:Name="test" Click="test_Click" ></Button>
        </Grid>

    </Window>

XAML Code Behind:

          namespace WpfApplication1
    {
        /// <summary>
        /// Interaction logic for MainWindow1.xaml
        /// </summary>
        public partial class MainWindow1 : Window
        {
            RBViewModel _viewModel;

            public MainWindow1()
            {
                InitializeComponent();

                _viewModel = (RBViewModel)base.DataContext;


                for (int i = 0; i < 4; i++)
                {
                    _viewModel.AddRb("a" + i, true);

                }
            }

            private void test_Click(object sender, RoutedEventArgs e)
            {
                Console.WriteLine(_viewModel.GetChecked().RadioBase);
                _viewModel.ClearAllValues();
            }



        }


    }

Upvotes: 1

Martin Liversage
Martin Liversage

Reputation: 106826

If you want to stick to the MVVM pattern you should consider replacing the Grid control with an ItemsControl. You then need two view-models: the child view-model which is the one you have explained about in your question and a parent view-model that contains a collection of the child view models:

public ObservableCollection<FPGAViewModel> Children { get; set; }

    public ParentViewModel()
    {
        Children = new ObservableCollection<FPGAViewModel>();
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0x0" });
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0x40" });
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0x80" });
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0xc0" });
    }

If you want to be able to dynamically add and remove child items you should use a collection based on ObservableCollection<T> but it seems that you want to stick to exactly four child items.

The ItemsControl can generate items based on a template (ItemTemplate) for each item in the ItemsSource. These items will be placed in the ItemsPanel which by default is a StackPanel. Stacking the radio buttons on top of each is probably what you want.

<ItemsControl ItemsSource="{Binding Children}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical"
                    IsItemsHost="True" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <RadioButton Content="{Binding RadioBase}" Margin="0,10,0,0" IsChecked="{Binding BaseCheck}" Height="15" Width="80" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
</ItemsControl>

Note that the DataContext of the ItemsControl should be set to an instance of ParentViewModel. In MVVM this is done by binding the view containing the ItemsControl to the parent view-model. When ItemsControl generates child items each RadioButton will have a DataContext bound to each ChildViewModel instance and the bindings in the RadioButton will bind to that view-model.

Upvotes: 1

Vinit Sankhe
Vinit Sankhe

Reputation: 19885

Yopu can achieve dynamic generation of grouped RadioBoxes using following XAML & Binding

XAML:

<ListBox SelectionMode="Single"
         SelectedValue="{Binding CurrentRadioDescription}"
         SelectedValuePath="Description"
         ItemsSource="{Binding RadioBoxModelList}" 
    Focusable="True"
    KeyboardNavigation.IsTabStop="True"          
    VerticalAlignment="Center"
    BorderBrush="Transparent"
    BorderThickness="0"
    Background="Transparent" >
<ListBox.Resources>
    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
    Color="Transparent"/>
    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" 
    Color="Transparent"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.ControlDarkBrushKey}" 
    Color="Transparent"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.InactiveBorderBrushKey}" 
    Color="Transparent"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.ControlDarkDarkBrushKey}" 
    Color="Transparent"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.ControlLightBrushKey}" 
    Color="Transparent"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.ControlLightLightBrushKey}" 
    Color="Transparent"/> 
    <SolidColorBrush x:Key="{x:Static SystemColors.WindowBrushKey}" 
    Color="Transparent"/>
</ListBox.Resources>
<ListBox.ItemsPanel>
    <ItemsPanelTemplate>
    <StackPanel 
        Orientation="Horizontal"
        Background="Transparent"/>
    </ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
    <DataTemplate>
    <RadioButton 
          MinWidth="80"
                  Background="Transparent"
          IsChecked="{Binding Path=IsSelected, 
                  RelativeSource={RelativeSource 
                    AncestorType={x:Type ListBoxItem}},
                  Mode=TwoWay}"
         Content="{Binding Description, Mode=OneWay}" 
         Margin="-1"/>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

C#

public class RadioBoxModel : INotifyPropertyChanged { 
      //Raise property changed notifications in Setters below.
      public bool IsChecked { get; set; } 
      public string Description { get; set; }
}

Upvotes: 0

Prabhu Murthy
Prabhu Murthy

Reputation: 9261

for(i = 0; i < 4; i++)
{
    m_registerBase[i] = new RadioButton();        
    m_registerBase[i].IsChecked=true;
    //Sets the Binding programmatcially
    m_registerBase[i].SetBinding(RadioButton.Content, "MyContent");
}

The RadioButton Class

SetBinding

Upvotes: 0

Related Questions