Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF MVVM Radio buttons on ItemsControl

Tags:

I've bound enums to radio buttons before, and I generally understand how it works. I used the alternate implementation from this question: How to bind RadioButtons to an enum?

Instead of enumerations, I'd like to generate a runtime-enumerated set of a custom type and present those as a set of radio buttons. I have gotten a view working against a runtime-enumerated set with a ListView, binding to the ItemsSource and SelectedItem properties, so my ViewModel is hooked up correctly. Now I am trying to switch from a ListView to a ItemsControl with radio buttons.

Here's as far as I've gotten:

<Window.Resources>     <vm:InstanceToBooleanConverter x:Key="InstanceToBooleanConverter" /> </Window.Resources>  <!-- ... -->  <ItemsControl ItemsSource="{Binding ItemSelections}">     <ItemsControl.ItemTemplate>         <DataTemplate DataType="{x:Type vm:ISomeType}">             <RadioButton Content="{Binding Name}"                          IsChecked="{Binding Path=SelectedItem, Converter={StaticResource InstanceToBooleanConverter}, ConverterParameter={Binding}}"                          Grid.Column="0" />         </DataTemplate>     </ItemsControl.ItemTemplate> </ItemsControl> 

InstanceToBooleanConverter has the same implementation as EnumToBooleanConverter from that other question. This seems right, since it seems like it just invokes the Equals method:

public class InstanceToBooleanConverter : IValueConverter {     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)     {         return value.Equals(parameter);     }      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)     {         return value.Equals(true) ? parameter : Binding.DoNothing;     } } 

The problem I am getting now is that I can't figure out how to send a runtime value as the ConverterParameter. When I try (with the code above), I get this error:

A 'Binding' cannot be set on the 'ConverterParameter' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Is there a way to bind to the item instance, and pass it to the IValueConverter?

like image 323
Merlyn Morgan-Graham Avatar asked May 05 '11 02:05

Merlyn Morgan-Graham


1 Answers

It turns out that it is much simpler to abandon using ItemsControl and instead go with ListBox.

It may be more heavy-weight, but that's mostly because it is doing the heavy lifting for you. It is really easy to do a two-way binding between RadioButton.IsChecked and ListBoxItem.IsSelected. With the proper control template for the ListBoxItem, you can easily get rid of all the selection visual.

<ListBox ItemsSource="{Binding Properties}" SelectedItem="{Binding SelectedItem}">     <ListBox.ItemContainerStyle>         <!-- Style to get rid of the selection visual -->         <Style TargetType="{x:Type ListBoxItem}">             <Setter Property="Template">                 <Setter.Value>                     <ControlTemplate TargetType="{x:Type ListBoxItem}">                         <ContentPresenter />                     </ControlTemplate>                 </Setter.Value>             </Setter>         </Style>     </ListBox.ItemContainerStyle>     <ListBox.ItemTemplate>         <DataTemplate DataType="{x:Type local:SomeClass}">             <RadioButton Content="{Binding Name}" GroupName="Properties">                 <!-- Binding IsChecked to IsSelected requires no support code -->                 <RadioButton.IsChecked>                     <Binding Path="IsSelected"                              RelativeSource="{RelativeSource AncestorType=ListBoxItem}"                              Mode="TwoWay" />                 </RadioButton.IsChecked>             </RadioButton>         </DataTemplate>     </ListBox.ItemTemplate> </ListBox> 
like image 175
Merlyn Morgan-Graham Avatar answered Sep 28 '22 07:09

Merlyn Morgan-Graham