Search code examples
c#wpflabeldatatemplatelistviewitem

how to access label name in nested listview datatemplate on a check box event


I have defined a label with name and I'm trying to access it but no luck. Let me explain my problem with my code.

   <ListView Name="gridListView" ItemsSource="{Binding... }">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="Focusable" Value="false"/>
                </Style>
            </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <Border>
                    <StackPanel Orientation="Vertical">
                        <Label x:Name="vLabel" Content="{Binding VCValue}"/>
                        <ListView Name="checkBoxListView" ItemsSource="{Binding CList}">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <CheckBox Margin="5" Click="CheckBox_Click" IsChecked="{Binding SelectedValue, Mode=TwoWay}"  Content="{Binding Current, Mode=OneWay }"/>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

In the above code, I have two listview, gridListView and checkBoxListView. Here, I want to access the label vLabel which is inside the datatemplate of gridListView when the one of the value in checkbox(which is inside checkBoxListView) is clicked. I understand it can't be accessed directly as its within datatemplate so i tried below code as suggested in other forums but gridListView.SelectedIndex is always -1 so i know i'm not doing the right thing. When I just hardcoded gridListView.SelectedIndex to index 0, 1 or 2 its giving me the right value of vLabel so the below code will work if gridListView.SelectedIndex is correct.

private void CheckBox_Click(object sender, RoutedEventArgs e)
    {
        CheckBox chk =(CheckBox)sender;
        int index = gridListView.Items.IndexOf(chk.DataContext);
        ListViewItem item = gridListView.ItemContainerGenerator.ContainerFromIndex(gridListView.SelectedIndex) as ListViewItem;
        if (item!=null)
        {
            //get the item's template parent
            ContentPresenter templateParent = GetFrameworkElementByName<ContentPresenter>(item);
            DataTemplate dataTemplate = gridListView.ItemTemplate;
            if (dataTemplate != null && templateParent != null)
            {
                var lab = dataTemplate.FindName("vLabel", templateParent) as Label;
                var v = lab.Content;
            }
        }   

private static T GetFrameworkElementByName<T>(FrameworkElement referenceElement) where T : FrameworkElement
    {
     //I can post this function if need be
       ....
    }

Appreciate any help that will help me access vLabel.

Thanks in advance


Solution

  • Thank you for all your guidance. I did get hint from Milan's code to achieve solution for my issue. Here, I'm trying to get reference parent of listviewItem(i.e stackpanel) and then access its child. In my case, stack panels child at index 0 is Label and at index 1 is ListView. So then I go through visualtreehelper to get reference to its child at index 0 which is what i need access to. So here is the code snippet.

    private void CheckBox_Click(object sender, RoutedEventArgs e)
        {
            CheckBox checkBox = (CheckBox)sender;            
            //to access parent of the checkbox
            ListViewItem listViewItem =
            GetVisualAncestor<ListViewItem>((DependencyObject)sender);
            //to access parent of the listViewItem(which is parent of checkbox)
            StackPanel stackPanel =
            GetVisualAncestor<StackPanel>((DependencyObject)listViewItem);
    
            int childCount = VisualTreeHelper.GetChildrenCount(stackPanel);
            //to access child of stackpanel to access the current vLabel 
            var vValue = VisualTreeHelper.GetChild(stackPanel, 0) as Label;
    }
    
    private static T GetVisualAncestor<T>(DependencyObject o)where T : DependecyObject
    {
        ...
    }