如何发送嵌套集合的 ItemsControl 项目位置
How to send an ItemControl Item's location for nested collections
我有一个绑定到 ObservableCollection<ObservableCollection<BookModel>>
的 ItemControl。最深的 ItemControl 中的每个项目都有一个按钮。我实现了一个每次单击按钮时都会触发的命令。
我的问题是我不知道应该将哪个参数传递给执行方法才能知道哪个 Item 触发了命令。意思是,如果按钮用作 "Add Book" 按钮,我想知道我应该在哪里插入 BookModel 对象
<UserControl.Resources>
<DataTemplate x:Key="BooksViewTemplate">
<StackPanel>
<TextBlock>
<!-- This is where I bind data to the BookModel -->
</TextBlock>
<Button x:Name="AddNewBook"
Command="{Binding ElementName=LayoutRoot, Path = DataContext.AddBookCommand}"
<!-- CommandParameter= -->
/>
</StackPanel>
</<DataTemplate>
<DataTemplate x:Key="DataTemplate_level1">
<StackPanel>
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource BooksViewTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<ItemsControl ItemsSource="{Binding Books}" ItemTemplate="{DynamicResource DataTemplate_level1}" DataContext="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
public ICommand AddBookCommand
{
get
{
return _addBookCommnad ?? (_addBookCommand = new CmandHandler<object>((par) => AddBookAction(par), _canExecute));
}
}
public void AddBookAction(object obj)
{
//This is where I want to add a new BookModel to the
IObservableCollection<IObservableCollection<BookModel>> at the location
given by the pressed button
}
您可以使用 AlternationIndex
属性 来获取索引。只需将 ItemsControl
中的 AlternationCount
设置为 int.MaxValue
:
<ItemsControl ItemsSource="{Binding yourcollection}" AlternationCount="2147483647">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
如果您将一个项目作为 CommandParameter 传递并在您的集合中搜索,那么它将起作用,如果您在集合中没有重复引用,否则它将失败(您不会知道你应该采取哪个实例)。
对于嵌套集合,您可以通过以下方式访问索引:
<ItemsControl ItemsSource="{Binding ColOfCol}" AlternationCount="2147483647">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding }" AlternationCount="2147483647">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource multivalcnv}">
<Binding Path='(ItemsControl.AlternationIndex)' RelativeSource="{RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}"></Binding>
<Binding Path='(ItemsControl.AlternationIndex)' RelativeSource="{RelativeSource AncestorType=ContentPresenter, AncestorLevel=1}"></Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public class MultValConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 2)
{
//return (values[0], values[1]); //For the ViewModel
return (values[0], values[1]).ToString(); //For the UI example
}
else
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException("It's a one way converter.");
}
}
我有一个绑定到 ObservableCollection<ObservableCollection<BookModel>>
的 ItemControl。最深的 ItemControl 中的每个项目都有一个按钮。我实现了一个每次单击按钮时都会触发的命令。
我的问题是我不知道应该将哪个参数传递给执行方法才能知道哪个 Item 触发了命令。意思是,如果按钮用作 "Add Book" 按钮,我想知道我应该在哪里插入 BookModel 对象
<UserControl.Resources>
<DataTemplate x:Key="BooksViewTemplate">
<StackPanel>
<TextBlock>
<!-- This is where I bind data to the BookModel -->
</TextBlock>
<Button x:Name="AddNewBook"
Command="{Binding ElementName=LayoutRoot, Path = DataContext.AddBookCommand}"
<!-- CommandParameter= -->
/>
</StackPanel>
</<DataTemplate>
<DataTemplate x:Key="DataTemplate_level1">
<StackPanel>
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource BooksViewTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<ItemsControl ItemsSource="{Binding Books}" ItemTemplate="{DynamicResource DataTemplate_level1}" DataContext="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
public ICommand AddBookCommand
{
get
{
return _addBookCommnad ?? (_addBookCommand = new CmandHandler<object>((par) => AddBookAction(par), _canExecute));
}
}
public void AddBookAction(object obj)
{
//This is where I want to add a new BookModel to the
IObservableCollection<IObservableCollection<BookModel>> at the location
given by the pressed button
}
您可以使用 AlternationIndex
属性 来获取索引。只需将 ItemsControl
中的 AlternationCount
设置为 int.MaxValue
:
<ItemsControl ItemsSource="{Binding yourcollection}" AlternationCount="2147483647">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
如果您将一个项目作为 CommandParameter 传递并在您的集合中搜索,那么它将起作用,如果您在集合中没有重复引用,否则它将失败(您不会知道你应该采取哪个实例)。
对于嵌套集合,您可以通过以下方式访问索引:
<ItemsControl ItemsSource="{Binding ColOfCol}" AlternationCount="2147483647">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding }" AlternationCount="2147483647">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource multivalcnv}">
<Binding Path='(ItemsControl.AlternationIndex)' RelativeSource="{RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}"></Binding>
<Binding Path='(ItemsControl.AlternationIndex)' RelativeSource="{RelativeSource AncestorType=ContentPresenter, AncestorLevel=1}"></Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public class MultValConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 2)
{
//return (values[0], values[1]); //For the ViewModel
return (values[0], values[1]).ToString(); //For the UI example
}
else
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException("It's a one way converter.");
}
}