Reputation: 397
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
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
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
Reputation: 19885
Yopu can achieve dynamic generation of grouped RadioBox
es 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
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");
}
Upvotes: 0