3
votes

I use MVVM Light (WPF). I want to build a menu of checkboxes styled as ToggleButtons in a ListView and show some controls in a contentcontrol depending on which checkbox is being checked. The ItemSource of the ListView I have set to an ObservableCollection<ViewModelInfo> where the ViewModelInfo objects holds information about the ViewModel and View to show. The listview's SelectedItem I have bound to a SelectedViewModelInfoItem property on the ViewModel. The SelectedViewModelInfoItem property will grab the information from the selected ViewModelInfo item and set the correct content control.

<ListView Grid.Column="0" Grid.Row="0" Grid.RowSpan="10" 
          ItemsSource="{Binding LeftPaneViewModelInfoItems}" 
          Background="Transparent" SelectedItem="{Binding SelectedViewModelInfoItem}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <RadioButton Content="{Binding Text}" 
                         Style="{StaticResource RadioButtonToggleButtonStyle}" 
                         GroupName="DisplayPage"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

The problem I see is that the selection of the ListView seems completely separate from the RadioButtons checked state, so I have to click next to the toggle button to select it also I get an overlay color from the ListView.

Question: How do I easiest show my collection of ViewModeInfo as a list of togglebuttons making sure I only see a list of togglebuttons (not the highlight overlay from the ListView) still making sure the selected (checked togglebutton) is set as the SelectedViewModelInfoItem.

I should mention I have explored the EventToCommand, binding the Radiobutton's Checked event to a RelayCommand on the ViewModel. It would work if I could just get the actual ViewModelItem as an event argument instead of the default EventArgs (which source is the radiobutton). I was not able to solve it that way, but if there is a way to get the ViewModelItem as the eventarg it could be a nice solution.

1
You may use an ItemsControl (which does not provide selection) and bind the RadioButton's IsChecked property to your view model item. - Clemens
But how can I then get which ViewModelInfo that is checked? - Johan
Each ViewModelInfo would have a boolean property that you would bind to. As a note, setting UpdateSourceTrigger=PropertyChanged on the ItemsSource binding is pointless. It has no effect in a OneWay Binding like this. - Clemens
@Clemens I guess, @Johan doesn't have any bool property with his model to represent the Selection. I see that, he is relying on the ListView's SelectedItem to get the checked item. - dhilmathy
@Clemens, Yeah, definitely. It's one more way of getting the selected item. Personally, i see it'll be more helpful when multiple selection is needed. - dhilmathy

1 Answers

5
votes

You can bind the IsSelected property of the ListViewItem to IsChecked property of RadioButton to achieve this. Like,

<ListView  Grid.Column="0" Grid.Row="0" Grid.RowSpan="10" 
           ItemsSource="{Binding LeftPaneViewModelInfoItems}" 
           Background="Transparent" SelectedItem="{Binding SelectedViewModelInfoItem}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <RadioButton Content="{Binding Text}" 
                         Style="{StaticResource RadioButtonToggleButtonStyle}" 
                         GroupName="DisplayPage"
                         IsChecked="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

If you want to completely remove the Selection background colouring completely, you can use below ItemContainerStyle along with above change.

<ListView.ItemContainerStyle>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <ContentPresenter />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ListView.ItemContainerStyle>