如何在复选框事件上访问嵌套listview datatemplate中的标签名称

问题描述 投票:-1回答:2

我已经定义了一个带有名称的标签,我正试图访问它,但没有运气。让我用我的代码解释我的问题。

   <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的datatemplate内的标签vLabel。我明白它不能直接访问,因为它在datatemplate内,所以我尝试下面的代码,如其他论坛建议但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的帮助。

提前致谢

c# wpf label datatemplate listviewitem
2个回答
0
投票

您将焦点设置为false,因此您无法通过单击选择项目。复选框检查也会在选择之前发生,即使你将焦点设置为true,所以选择的索引仍然是-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;  
}

然后做你想做的事情?


0
投票

感谢您的所有指导。我确实得到了米兰代码的提示,以便为我的问题找到解决方案。在这里,我试图获得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
{
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.