如何在复选框事件中访问嵌套列表视图数据模板中的标签名称

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

我已经用名称定义了一个标签,我正在尝试访问它,但没有成功。让我用我的代码解释我的问题。

   <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>

在上面的代码中,我有两个listview,gridListView和checkBoxListView。在这里,当单击复选框中的值之一(位于 checkBoxListView 内)时,我想访问位于 gridListView 的数据模板内的标签 vLabel。 我知道它不能直接访问,因为它在数据模板中,所以我按照其他论坛中的建议尝试了下面的代码,但 gridListView.SelectedIndex 始终是 -1,所以我知道我没有做正确的事情。当我刚刚将 gridListView.SelectedIndex 硬编码为索引 0、1 或 2 时,它为我提供了正确的 vLabel 值,因此如果 gridListView.SelectedIndex 正确,下面的代码将起作用。

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
       ....
    }

感谢任何帮助我访问 vLabel 的帮助。

提前致谢

您正在将 focusable 设置为 false,因此您无法 select 单击该项目。 checkbox-checked 也发生在 selection 之前,即使您将 focusable 设置为 true,所以 selected 索引仍然是 -1。

您可以像这样简单地找到您的标签:

public Label FindLabel(CheckBox checkBox)
{
   var listView = VisualTreeHelper.GetParent(checkBox);
   while (listView.GetType() != typeof(ListView))
   {
       listView = VisualTreeHelper.GetParent(listView);
   }
   return (listView as FrameworkElement).FindName("vLabel") as Label;
}

但我建议您告诉我们您想要实现的目标,因为这似乎不是一个干净的解决方案。

你能不能在你的 StackPanel 上做这个:

 <StackPanel CheckBox.Checked="CheckBox_Click"  Orientation="Vertical">

然后按如下方式访问您想要的两个属性:

private void CheckBox_Click(object sender, RoutedEventArgs e)
{
    var outerItem = (sender as FrameworkElement).DataContext;
    var innerItem = (e.OriginalSource as FrameworkElement).DataContext;  
}

然后为所欲为?

感谢您的指导。我确实从 Milan 的代码中得到提示来解决我的问题。在这里,我试图获取 listviewItem(即 stackpanel)的引用父级,然后访问其子级。在我的例子中,索引 0 处的堆栈面板子项是 Label,索引 1 处是 ListView。因此,然后我通过 visualtreehelper 在索引 0 处获取对其子项的引用,这是我需要访问的。所以这是代码片段。

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
{
    ...
}