Reputation: 3515
I just finished with watching practical mvvm presentation video on youtube and if I understand correctly moving logic from codebehing to view model is good practice and we should strive to this pattern.
Having this in mind I have one simple question. Inside xaml I have four radio buttons
<StackPanel x:Name="panel">
<RadioButton GroupName="myGroup" Name="Option1" Content="option one" IsChecked="True" Width="40"/>
<RadioButton GroupName="myGroup" Name="Option2" Content="option two" IsChecked="False" Width="80"/>
<RadioButton GroupName="myGroup" Name="Option3" Content="option three" IsChecked="False" Width="60"/>
</StackPanel>
I want to use this code inside viewmodel below to fetch selected radio btn.
var checkedValue = panel.Children.OfType<RadioButton>()
.FirstOrDefault(r => r.IsChecked.HasValue && r.IsChecked.Value);
Question is: How can I access to this panel object from the viewmodel? It's not data to use binding.
Update: as @Rohit Vatss said "View objects should not be accessed from ViewModel" I would change question to How to know which radio button is selected using viewmodel?
Upvotes: 0
Views: 206
Reputation: 33364
You can do it by creating one property in you ViewModel, lets say GroupIndex
private int _groupIndex = 1;
public int GroupIndex
{
get { return _groupIndex; }
set
{
if (_groupIndex == value) return;
_groupIndex = value;
OnPropertyChanged("GroupIndex");
}
}
then create simple converter which will convert current GroupIndex
value to true or false and back:
public class IndexBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
return false;
else
return (int)value == System.Convert.ToInt32(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
return null;
else if ((bool)value)
return System.Convert.ToInt32(parameter);
else
return DependencyProperty.UnsetValue;
}
}
and then bind your RadioButton
to GroupIndex
which will will be set to 1, 2 or 3 depending on which RadioButton
is checked
<StackPanel>
<StackPanel.Resources>
<local:IndexBooleanConverter x:Key="IndexBooleanConverter"/>
</StackPanel.Resources>
<RadioButton Content="Option1" IsChecked="{Binding Path=GroupIndex, Converter={StaticResource IndexBooleanConverter}, ConverterParameter=1}"/>
<RadioButton Content="Option2" IsChecked="{Binding Path=GroupIndex, Converter={StaticResource IndexBooleanConverter}, ConverterParameter=2}"/>
<RadioButton Content="Option3" IsChecked="{Binding Path=GroupIndex, Converter={StaticResource IndexBooleanConverter}, ConverterParameter=3}"/>
</StackPanel>
In this case GroupIndex
is int
but you can also use same logic if for example your GroupIndex
is an enum
Upvotes: 1
Reputation: 473
Well an aprroach would be for example using a Command and a Command Parameter on the radiobuttons Binded to your viewmodel. For example:
<RadioButton GroupName="myGroup" Name="Option1" Content="option one" IsChecked="True" Width="40" Command="{Binding RbCheckedCommand}" CommandParameter="RB1"/>
<RadioButton GroupName="myGroup" Name="Option2" Content="option two" IsChecked="False" Width="80" Command="{Binding RbCheckedCommand}" CommandParameter="RB2"/>
<RadioButton GroupName="myGroup" Name="Option3" Content="option three" IsChecked="False" Width="60" Command="{Binding RbCheckedCommand}" CommandParameter="RB3"/>
Then on your ViewModel:
private readonly DelegateCommand<object> rbCheckedCommand;
public ICommand RbCheckedCommand
{
get { return this.rbCheckedCommand; }
}
private void RbCheckedCommandExecute(object obj)
{
string rbselected = obj.ToString();
}
And on the constructor of the class:
this.rbCheckedCommand = new DelegateCommand<object>(RbCheckedCommandExecute);
You will have to use the prism adding:
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
And making your class inherits from NotificationObject so you can use the Property changed easily.
Hope it helps.
Upvotes: 0