这是我在列表框中的用户模板。我想点击列表框的任何复选框都有“listbox.selectedindex”。我想知道选中哪一行,复选框。在复选框的点击事件中,它应该聚焦整个选定的行。
<ListView x:Name="listbox3" Visibility="Visible" Margin="540,168,37,46" IsSynchronizedWithCurrentItem="True" BorderBrush="Black">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Width="200" >
<TextBlock Text="{Binding VmName}" Width="129" Visibility="Visible" />
<CheckBox x:Name="cb" IsThreeState="False" IsChecked="{Binding IsCheck, Mode=TwoWay}" Margin="6,0,18,6" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<CheckBox x:Name="cb1" IsThreeState="False" IsChecked="{Binding IsCheck1, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
答案 0 :(得分:1)
如果没有明确说明问题的a good, minimal, complete code example,很难确切地知道哪些建议对您最有用。如果没有a clear problem statement,你甚至不清楚你希望代码做什么。
但是,如果我理解正确,您将使用DataTemplate
中相应的ListView
对象显示某些数据项类型。用户可以切换复选框,并且您想要更新ListView
中当前选定的项目,以便它始终是包含刚刚切换的复选框的项目。
至少有几种合理的方法可以做到这一点。在这两种情况下,您只需将ListView.SelectedValue
属性设置为与正在修改的CheckBox
对应的数据项对象引用。
第一种方法是处理Checked
控件本身上的Unchecked
和CheckBox
事件,跟踪回ListViewItem
,然后获取ListViewItem
的数据项
首先,您需要编写一个处理程序来执行上述操作:
private void cb_Checked(object sender, RoutedEventArgs e)
{
ListViewItem listViewItem =
GetVisualAncestor<ListViewItem>((DependencyObject)sender);
listbox3.SelectedValue =
listbox3.ItemContainerGenerator.ItemFromContainer(listViewItem);
}
private static T GetVisualAncestor<T>(DependencyObject o) where T : DependencyObject
{
do
{
o = VisualTreeHelper.GetParent(o);
} while (o != null && !typeof(T).IsAssignableFrom(o.GetType()));
return (T)o;
}
请注意辅助方法GetVisualAncestor<T>()
。它使用VisualTreeHelper
将树移回包含受影响的ListViewItem
控件的CheckBox
对象。
找到此对象后,代码会调用ItemContainerGenerator.ItemFromContainer()
来查找实际的数据项对象引用,并将此引用分配给SelectedValue
属性。
当然,要使处理程序有用,您需要将其订阅到相关的Checked
和Unchecked
事件。例如:
<DataTemplate DataType="{x:Type local:DataItem}">
<StackPanel Orientation="Horizontal" Width="200" >
<TextBlock Text="{Binding VmName}" Width="129" Visibility="Visible" />
<CheckBox x:Name="cb" IsThreeState="False"
IsChecked="{Binding IsChecked1, Mode=TwoWay}"
Margin="6,0,18,6"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Checked="cb_Checked" Unchecked="cb_Checked"/>
<CheckBox x:Name="cb1" IsThreeState="False"
IsChecked="{Binding IsChecked2, Mode=TwoWay}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Checked="cb_Checked" Unchecked="cb_Checked"/>
</StackPanel>
</DataTemplate>
(由于你没有提供一个完整的代码示例,其中包含了数据项对象类,我只根据你的问题编写了自己的代码。我更改了属性名称,使它们更有意义,即{{ 1}}和IsChecked1
。请随意使用您自己的属性名称:))。
第二种方式在一方面更直接,但在另一方面稍微不那么直接。也就是说,假设您的数据项对象类实现IsChecked2
,您可以为每个数据项对象订阅INotifyPropertyChanged
事件,并简单地将事件的PropertyChanged
指定为{{1}属性。
这更直接,因为您不必添加将可视树移回某个控件的父级的代码。但它也不那么直接,因为您需要将必要的事件处理程序附加到每个数据项对象的代码。
一个例子可能如下所示:
sender
请注意,在上面的示例中,我在任何属性更改上分配ListView.SelectedValue
属性。在我自己的代码示例中,这很好,因为可以更改的唯一属性是与复选框相关的属性。当然,如果要在任何属性值更改上选择相应的List<DataItem> dataItems = new List<DataItem>
{
new DataItem { VmName = "sagar" },
new DataItem { VmName = "kaustubh" },
new DataItem { VmName = "gaurav" },
new DataItem { VmName = "abhi" },
};
listbox3.ItemsSource = dataItems;
PropertyChangedEventHandler handler =
(sender, e) => listbox3.SelectedValue = sender;
foreach (DataItem item in dataItems)
{
item.PropertyChanged += handler;
}
项,这也可以。但是,如果您真的只想更新SelectedValue
和ListView
属性的更改,则需要查看处理程序中的属性名称。 E.g:
IsChecked1
以下是我为上述两种方法的代码示例编写的IsChecked2
类:
PropertyChangedEventHandler handler = (sender, e) =>
{
if (e.PropertyName == "IsChecked1" || e.PropertyName == "IsChecked2")
{
listbox3.SelectedValue = sender;
}
}