The Rubberduck 2.0 Code Inspections UI was recently redesigned (again!), this time featuring a GroupingGrid control (thanks @BrunoCosta!), and what appears to be a dynamic grouping:ResourcesThe UserControl's resources include two CollectionViewSource definitions, which determine the sorting and grouping rules for the user-selectable grouping styles.<UserControl x:Class=Rubberduck.UI.CodeInspections.InspectionResultsControl             xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation             xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml             xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006              xmlns:d=http://schemas.microsoft.com/expression/blend/2008             xmlns:inspections=clr-namespace:Rubberduck.Inspections             xmlns:resx=clr-namespace:Rubberduck.UI             xmlns:codeInspections=clr-namespace:Rubberduck.UI.CodeInspections             xmlns:controls=clr-namespace:Rubberduck.UI.Controls             xmlns:componentModel=clr-namespace:System.ComponentModel;assembly=WindowsBase             ResxExtension.DefaultResxName=Rubberduck.UI.RubberduckUI              Language={UICulture}             mc:Ignorable=d              d:DesignHeight=300 d:DesignWidth=300              d:DataContext={d:DesignInstance codeInspections:InspectionResultsViewModel}><UserControl.Resources>    <BooleanToVisibilityConverter x:Key=BoolToVisibility/>    <Style x:Key=LinkButton TargetType=Button BasedOn={StaticResource ResourceKey={x:Type Button}}>        <!-- irrelevant -->    </Style>    <codeInspections:InspectionSeverityImageSourceConverter x:Key=SeverityIconConverter />    <codeInspections:InspectionImageSourceConverter x:Key=InspectionIconConverter />    <codeInspections:InspectionTypeConverter x:Key=InspectionTypeConverter />    <Style x:Key=IconStyle TargetType=Image>        <Setter Property=Height Value=16 />        <Setter Property=Width Value=16 />        <Setter Property=Margin Value=4 />    </Style>    <CollectionViewSource x:Key=ResultsByInspectionType Source={Binding Results}>        <CollectionViewSource.SortDescriptions>            <componentModel:SortDescription PropertyName=Inspection.Name/>        </CollectionViewSource.SortDescriptions>        <CollectionViewSource.GroupDescriptions>            <PropertyGroupDescription PropertyName=Inspection Converter={StaticResource InspectionTypeConverter} />        </CollectionViewSource.GroupDescriptions>    </CollectionViewSource>    <CollectionViewSource x:Key=ResultsByModule Source={Binding Results}>        <CollectionViewSource.SortDescriptions>            <componentModel:SortDescription PropertyName=QualifiedSelection.QualifiedName.ComponentName/>        </CollectionViewSource.SortDescriptions>        <CollectionViewSource.GroupDescriptions>            <PropertyGroupDescription PropertyName=QualifiedSelection.QualifiedName />        </CollectionViewSource.GroupDescriptions>    </CollectionViewSource></UserControl.Resources>ContentSo, here's the actual control:<Grid>    <Grid.RowDefinitions>        <RowDefinition Height=30/>        <RowDefinition Height=* MinHeight=64 />        <RowDefinition Height=5/>        <RowDefinition Height=Auto MinHeight=48/>    </Grid.RowDefinitions>    <Border Grid.Row=0 Grid.RowSpan=3 Background=#FFEEF5FD />    <ToolBar Grid.Row=0>        <Button Command={Binding RefreshCommand}>            <Image Height=16 Source=../../Resources/arrow-circle-double.png />        </Button>        <Separator />        <Menu>            <MenuItem VerticalAlignment=Center                       Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=Fix}                      ItemsSource={Binding SelectedItem.QuickFixes}>                <MenuItem.Icon>                    <Image Height=16 Source=../../Resources/tick.png />                </MenuItem.Icon>                <MenuItem.ItemContainerStyle>                    <Style TargetType={x:Type MenuItem}>                        <Setter Property=Command Value={Binding Path=DataContext.QuickFixCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Menu, AncestorLevel=1}} />                        <Setter Property=CommandParameter Value={Binding} />                        <Setter Property=Header Value={Binding Description} />                    </Style>                </MenuItem.ItemContainerStyle>            </MenuItem>        </Menu>        <Menu>            <MenuItem Header=Grouping>                <MenuItem.Icon>                    <Image Height=16 Source=../../Resources/Microsoft/PNG/GroupBy_284_32.png />                </MenuItem.Icon>                <MenuItem x:Name=GroupByInspectionType  VerticalAlignment=Center Header=By inspection type IsChecked=True                           IsCheckable=True controls:MenuItemGroup.GroupName=GroupingStyle />                <MenuItem x:Name=GroupByModule VerticalAlignment=Center Header=By module                           IsCheckable=True controls:MenuItemGroup.GroupName=GroupingStyle />            </MenuItem>        </Menu>        <Separator />        <Button Command={Binding CopyResultsCommand}>            <Image Height=16 Source=../../Resources/document-copy.png />        </Button>    </ToolBar>    <controls:GroupingGrid Grid.Row=1 x:Name=ResultsByInspectionTypeGrid                           ShowGroupingItemCount=True                           SelectedItem={Binding SelectedItem}                           ItemsSource={Binding Source={StaticResource ResultsByInspectionType}}                           Visibility={Binding IsChecked, ElementName=GroupByInspectionType, Converter={StaticResource BoolToVisibility}}>        <DataGrid.Columns>            <DataGridTemplateColumn Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeInspectionResults_Type}>                <DataGridTemplateColumn.CellTemplate>                    <DataTemplate DataType=inspections:ICodeInspectionResult>                        <Image Source={Binding Inspection, Converter={StaticResource InspectionIconConverter}} Height=16 />                    </DataTemplate>                </DataGridTemplateColumn.CellTemplate>            </DataGridTemplateColumn>            <DataGridTextColumn Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeInspectionResults_Location} Binding={Binding QualifiedSelection.QualifiedName} />            <DataGridTextColumn Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeInspectionResults_Issue} Binding={Binding Description} />        </DataGrid.Columns>    </controls:GroupingGrid>    <controls:GroupingGrid Grid.Row=1 x:Name=ResultsByModuleGrid                           ShowGroupingItemCount=True                           SelectedItem={Binding SelectedItem}                           ItemsSource={Binding Source={StaticResource ResultsByModule}}                           Visibility={Binding IsChecked, ElementName=GroupByModule, Converter={StaticResource BoolToVisibility}}>        <DataGrid.Columns>            <DataGridTemplateColumn Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeInspectionResults_Type}>                <DataGridTemplateColumn.CellTemplate>                    <DataTemplate DataType=inspections:ICodeInspectionResult>                        <Image Source={Binding Inspection, Converter={StaticResource InspectionIconConverter}} Height=16 />                    </DataTemplate>                </DataGridTemplateColumn.CellTemplate>            </DataGridTemplateColumn>            <DataGridTextColumn Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeInspectionResults_Location} Binding={Binding QualifiedSelection.QualifiedName} />            <DataGridTextColumn Header={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeInspectionResults_Issue} Binding={Binding Description} />        </DataGrid.Columns>    </controls:GroupingGrid>    <resx:BusyIndicator Grid.Row=1 Width=36 Height=36 Visibility={Binding IsBusy, Converter={StaticResource BoolToVisibility}} />    <GridSplitter Grid.Row=2 Height=5 ShowsPreview=True Cursor=SizeNS HorizontalAlignment=Stretch/>    <Border Grid.Row=3 BorderThickness=0,1,0,0 BorderBrush=DimGray>        <StackPanel Orientation=Vertical MinHeight=48 Background=Gainsboro>            <StackPanel Margin=4 Orientation=Horizontal HorizontalAlignment=Stretch>                <Image Style={StaticResource IconStyle} VerticalAlignment=Center                        Source={Binding SelectedItem.Inspection.Severity, Converter={StaticResource SeverityIconConverter}}/>                <TextBlock Margin=4 Text={Binding SelectedItem.Inspection.Description} FontWeight=Bold TextWrapping=Wrap/>            </StackPanel>            <TextBlock Margin=4 Text={Binding SelectedItem.Inspection.Meta} FontSize=10 TextWrapping=Wrap/>            <TextBlock Margin=8 Text={Binding SelectedItem.QualifiedSelection} FontSize=10 TextWrapping=Wrap />            <WrapPanel>                <Button Style={StaticResource LinkButton} Margin=4                        Visibility={Binding CanExecuteQuickFixInModule, Converter={StaticResource BoolToVisibility}}                        Command={Binding QuickFixInModuleCommand}                        Content={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=QuickFix_ThisModule} />                <Button Style={StaticResource LinkButton} Margin=4                        Visibility={Binding CanExecuteQuickFixInProject, Converter={StaticResource BoolToVisibility}}                        Command={Binding QuickFixInProjectCommand}                        Content={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=QuickFix_ThisProject} />                <Button Style={StaticResource LinkButton} Margin=4                        Visibility={Binding CanDisableInspection, Converter={StaticResource BoolToVisibility}}                        Command={Binding DisableInspectionCommand}                        Content={Resx ResxName=Rubberduck.UI.RubberduckUI, Key=DisableThisInspection} />            </WrapPanel>        </StackPanel>    </Border></Grid>I'd like to bring your attention to this part:<controls:GroupingGrid Grid.Row=1 x:Name=ResultsByModuleGrid                       ShowGroupingItemCount=True                       SelectedItem={Binding SelectedItem}                       ItemsSource={Binding Source={StaticResource ResultsByModule}}                       Visibility={Binding IsChecked, ElementName=GroupByModule, Converter={StaticResource BoolToVisibility}}>And:<controls:GroupingGrid Grid.Row=1 x:Name=ResultsByInspectionTypeGrid                       ShowGroupingItemCount=True                       SelectedItem={Binding SelectedItem}                       ItemsSource={Binding Source={StaticResource ResultsByInspectionType}}                       Visibility={Binding IsChecked, ElementName=GroupByInspectionType, Converter={StaticResource BoolToVisibility}}>It completely reeks of a hack, but I haven't managed to get anything else to work. Is there any better way to do this? Copy-Pasta can't be the right way... right? ...Anything else smells in this markup?I can provide the C# ViewModel and related classes if additional context is needed, but I wanted this post to be about the markup.
Displaying inspection results, grouped per user selection
wpf;rubberduck;xaml
Apparently toggling visibility of controls like that, is common practice in WPF; there's no way to toggle the ItemsSource in xaml, so what you have is pretty much as good as it gets.Minor things stick out though:xmlns:resx=clr-namespace:Rubberduck.UIThe only thing in that namespace is the BusyIndicator control, which would be better off in the controls namespace.Probably an oversight, but every label is localized, except the ones in the Grouping menu, which are hard-coded:<MenuItem Header=Grouping>The x:Name attributes on the GroupingGrid controls shouldn't be needed (a quick search in the Rubberduck repository shows it's not referenced anywhere), get rid of them.