Search code examples
xamllistviewuwpuwp-xamlc++-winrt

UWP-CPP/Winrt Make a Line Control of the ListViewItem Data Template only visible when selected


I am planning to show a list of objects using ListView. According to the design when an Item is selected a blue line should appear in the content of the Item. I have written the below code and tried to change the visibility to visible (search for ----------Setting visibility Here in second code snippet) in Style of the ListViewItem defined as below. But doing so its throwing error. And I am not able to access the BlueLine object in the code behind when an ListViewItem is selected. Can you please help how this can be achieved. TIA

                <ListView
                    x:Name="ObjectList"
                    ItemsSource="{x:Bind ObjectViewModel.Objects}"
                    SelectionChanged="ListViewButtonClick"
                    MaxWidth ="{StaticResource ColumnMaximumWidth}"
                    VerticalAlignment = "Center"
                    HorizontalContentAlignment = "Stretch"
                    ScrollViewer.HorizontalScrollBarVisibility ="Disabled"
                    SelectionMode ="Single" />

                    <ListView.Resources>
                        <SolidColorBrush x:Key="ListViewItemBackgroundSelected" Color="Green" />
                        <SolidColorBrush x:Key="ListViewItemBackgroundSelectedPointerOver" Color="Green" />
                    </ListView.Resources>

                    <ListView.ItemContainerStyle>
                        <Style TargetType="ListViewItem">
                            <Setter Property="Margin" Value="0,0,0,30" />
                        </Style>
                    </ListView.ItemContainerStyle>

                    <ItemsControl.ItemTemplate>
                        <DataTemplate x:DataType="local:ObjectModel">
                                <Grid MinHeight="66" CornerRadius="8">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="auto" />
                                        <ColumnDefinition Width="auto" />
                                        <ColumnDefinition />
                                    </Grid.ColumnDefinitions>
                                    <Line
                                        x:Name="BlueLine"
                                        Stroke="Blue"
                                        StrokeThickness="4"
                                        Visibility="Collapsed"
                                        X1="0"
                                        X2="0"
                                        Y1="0"
                                        Y2="60" />
                                    <FontIcon
                                        Grid.Column="1"
                                        FontSize="17"
                                        Glyph="&#xE720;"
                                        Style="{StaticResource FontIconStyle1}" />
                                    <TextBlock
                                        Grid.Column="2"
                                        Style="{StaticResource AddBluetoothLabelTextStyle}"
                                        Text="{x:Bind ObjectName, Mode=OneWay}" />
                                </Grid>
                    </ItemsControl.ItemTemplate>
                </ListView>
<Style TargetType="ListViewItem">
                <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
                <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
                <Setter Property="Background" Value="{ThemeResource ListViewItemBackground}" />
                <Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}" />
                <Setter Property="TabNavigation" Value="Local" />
                <Setter Property="IsHoldingEnabled" Value="True" />
                <Setter Property="Padding" Value="12,0,12,0" />
                <Setter Property="HorizontalContentAlignment" Value="Left" />
                <Setter Property="VerticalContentAlignment" Value="Center" />
                <Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
                <Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}" />
                <Setter Property="AllowDrop" Value="False" />
                <Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
                <Setter Property="FocusVisualMargin" Value="0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                            <ListViewItemPresenter
                                x:Name="Root"
                                Margin="0,0,0,30"
                                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
                                CheckBrush="{ThemeResource ListViewItemCheckBrush}"
                                CheckMode="{ThemeResource ListViewItemCheckMode}"
                                ContentMargin="{TemplateBinding Padding}"
                                ContentTransitions="{TemplateBinding ContentTransitions}"
                                Control.IsTemplateFocusTarget="True"
                                CornerRadius="4"
                                DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
                                DragBackground="{ThemeResource ListViewItemDragBackground}"
                                DragForeground="{ThemeResource ListViewItemDragForeground}"
                                DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
                                FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
                                FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
                                FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
                                PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
                                PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}"
                                PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
                                PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
                                ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
                                RevealBackground="{ThemeResource ListViewItemRevealBackground}"
                                RevealBorderBrush="{ThemeResource ListViewItemRevealBorderBrush}"
                                RevealBorderThickness="{ThemeResource ListViewItemRevealBorderThemeThickness}"
                                SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
                                SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
                                SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
                                SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
                                SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal" />
                                        <VisualState x:Name="Selected">  ----------Setting visibility Here
                                            <VisualState.Setters>
                                                <Setter Target="BlueLine.Visibility" Value="Visible" />
                                            </VisualState.Setters>
                                        </VisualState>

                                        <VisualState x:Name="PointerOver">
                                            <VisualState.Setters>
                                                <Setter Target="Root.(RevealBrush.State)" Value="PointerOver" />
                                                <Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPointerOver}" />
                                            </VisualState.Setters>
                                        </VisualState>

                                        <VisualState x:Name="PointerOverSelected">
                                            <VisualState.Setters>
                                                <Setter Target="Root.(RevealBrush.State)" Value="PointerOver" />
                                                <Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPointerOver}" />
                                            </VisualState.Setters>
                                        </VisualState>
                                        <VisualState x:Name="PointerOverPressed">
                                            <VisualState.Setters>
                                                <Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
                                                <Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
                                            </VisualState.Setters>
                                        </VisualState>

                                        <VisualState x:Name="Pressed">
                                            <VisualState.Setters>
                                                <Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
                                                <Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
                                            </VisualState.Setters>
                                        </VisualState>

                                        <VisualState x:Name="PressedSelected">
                                            <VisualState.Setters>
                                                <Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
                                                <Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
                                            </VisualState.Setters>
                                        </VisualState>

                                    </VisualStateGroup>

                                    <VisualStateGroup x:Name="DisabledStates">
                                        <VisualState x:Name="Enabled" />

                                        <VisualState x:Name="Disabled">
                                            <VisualState.Setters>
                                                <Setter Target="Root.RevealBorderThickness" Value="0" />
                                            </VisualState.Setters>
                                        </VisualState>

                                    </VisualStateGroup>

                                </VisualStateManager.VisualStateGroups>
                            </ListViewItemPresenter>

                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style> 

Solution

  • There is an approach could be used to access the BlueLine object in code behind when a ListViewItem is selected by using VisualTreeHelper class.

    Please check the following code:

    Add headers and namespaces:

    #include <winrt/Windows.UI.Xaml.Shapes.h>
    #include <winrt/Windows.UI.Xaml.Media.h>
    
    using namespace winrt::Windows::UI::Xaml::Shapes;
    using namespace Windows::UI::Xaml::Media;
    

    Add a private member in .h file:

    private:
        Line previousLine{ nullptr };
    

    Access the BlueLine object in code behind:

    void winrt::ListViewStyle::implementation::MainPage::ObjectList_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
    {
        if (previousLine != nullptr)
        {
            previousLine.Visibility(Visibility::Collapsed);
        }
        auto selectedItemContainer = ObjectList().ContainerFromItem(ObjectList().SelectedItem());
        auto presenter = VisualTreeHelper::GetChild(selectedItemContainer.try_as<DependencyObject>(), 0);
        auto grid = VisualTreeHelper::GetChild(presenter, 0);
        auto line = VisualTreeHelper::GetChild(grid, 0).try_as<Line>();
        line.Visibility(Visibility::Visible);
        previousLine = line;
    }