如何获取 ItemsControl DataTemplate 的 "selected" 实例?

How do I get the "selected" instance of an ItemsControl DataTemplate?

我创建了一个动态表单,允许用户使用 ItemsControl 添加项目的变体。

                    <ItemsControl x:Name="variationItemsControl"
                              ItemsSource="{Binding FormItem.Variations}"
                              Visibility="Collapsed">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width=".60*"/>
                                    <ColumnDefinition Width=".30*"/>
                                </Grid.ColumnDefinitions>

                                <StackPanel Grid.Column="0" Margin="0,0,1,0">
                                    <TextBlock
                                        Foreground="White"
                                        Text="Variation Name"/>
                                    <TextBox
                                        x:Name="variationName"
                                        Style="{StaticResource FlyoutField}"
                                        Text="{Binding VariationName, Mode=TwoWay}"/>
                                </StackPanel>
                                <StackPanel Grid.Column="1">
                                    <TextBlock
                                        Foreground="White"
                                        Text="Price"/>
                                    <TextBox
                                        Style="{StaticResource FlyoutField}"
                                        Text="{Binding VariationPrice, Mode=TwoWay}"/>
                                </StackPanel>
                                <Button 
                                    Grid.Column="2" 
                                    Margin="0,0,0,6" 
                                    Content="X" 
                                    HorizontalAlignment="Stretch"
                                    Click="deleteVariationButton_Click"/>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

在网格中,有一个按钮,单击该按钮后,我希望删除该模板实例。例如,在下图中,如果我单击 12 盎司的 'X' 按钮。项,应删除该项。

从 ItemsControl 的 ItemsSource 中删除该实例是一件简单的事情,但我需要知道如何在 'X' 按钮单击事件中执行此操作。对象发送者是按钮本身,RoutedEventArgs 似乎没有包含任何我可以使用的相关信息。

private void deleteVariationButton_Click(object sender, RoutedEventArgs e)
{
    // what do I do here?      
}

有没有办法获取我点击的'X'按钮所在的模板容器的索引?如果我能得到那个索引,那么它就是从 ItemsControl 的 ItemsSource 容器中简单删除。

编辑更多代码:

public class Item : ObservableObject, IEquatable<Item>
{
    private string itemName;
    public string ItemName
    {
        get { return itemName; }
        set { Set<string>(() => ItemName, ref itemName, value.ToString().Trim()); }
    }

    private Category itemCategory;
    public Category ItemCategory
    {
        get { return itemCategory; }
        set { Set<Category>(() => ItemCategory, ref itemCategory, value); }
    }

    private decimal? singlePrice;
    public decimal? SinglePrice
    {
        get { return singlePrice; }
        set { Set<decimal?>(() => SinglePrice, ref singlePrice, value); }
    }

    private ObservableCollection<Variation> variations;
    public ObservableCollection<Variation> Variations
    {
        get { return variations; }
        set { Set<ObservableCollection<Variation>>(() => Variations, ref variations, value); }
    }

    private bool hasVariations;
    public bool HasVariations
    {
        get { return hasVariations; }
        set { Set<bool>(() => HasVariations, ref hasVariations, value); }
    }

    public Item()
    {
        itemCategory = new Category();
        Variations = new ObservableCollection<Variation>();
    }

    public Item(Item other)
    {
        Copy(other);
    }

    public void Copy(Item other)
    {
        if (this != other)
        {
            ItemName = other.ItemName;
            ItemCategory = new Category();
            ItemCategory.CategoryName = other.ItemCategory.CategoryName;
            ItemCategory.CategoryColor = other.ItemCategory.CategoryColor;
            SinglePrice = other.SinglePrice;
            Variations = new ObservableCollection<Variation>();

            foreach (Variation v in other.variations)
            {
                variations.Add(new Variation(v));
            }
        }
    }

    public bool Equals(Item other)
    {
        if (variations.Count() != other.variations.Count())
            return false;

        for (int i = 0; i < variations.Count(); i++)
        {
            if (!variations.ElementAt(i).Equals(other.variations.ElementAt(i)))
                return false;
        }

        if (itemName == other.itemName &&
            itemCategory.CategoryName == other.itemCategory.CategoryName &&
            itemCategory.CategoryColor == other.itemCategory.CategoryColor &&
            singlePrice == other.singlePrice &&
            hasVariations == other.hasVariations)
            return true;

        return false;
    }

    public class Variation : ObservableObject
    {
        public RelayCommand DeleteVariationCommand { get; private set; }

        private string variationName;
        public string VariationName
        {
            get { return variationName; }
            set { Set<string>(() => VariationName, ref variationName, value.ToString().Trim()); }
        }

        private decimal? variationPrice;
        public decimal? VariationPrice
        {
            get { return variationPrice; }
            set { Set<decimal?>(() => VariationPrice, ref variationPrice, value); }
        }

        public Variation()
        {
            variationName = "";
            variationPrice = 0M;

            DeleteVariationCommand = new RelayCommand(
                () => DeleteVariation(),
                () => CanDeleteVariation());
        }

        public void DeleteVariation()
        {

        }

        public bool CanDeleteVariation()
        {
            return true;
        }

        public Variation(Variation other)
        {
            variationName = other.variationName;
            variationPrice = other.variationPrice;
        }

        public bool Equals(Variation other)
        {
            if (variationName.Equals(other.variationName) && variationPrice == other.variationPrice)
                return true;

            return false;
        }
    }
}

绑定到按钮的命令 属性,而不是使用路由事件。如果这样做,您可以使用绑定的 RelativeSource 属性 来查找项目的 ItemsControl 父级,它应该具有包含要删除的项目的列表的 DataContext。

将 CommandParameter 设置为 {Binding} 以便删除命令知道要从列表中删除哪个项目。

您可以为删除按钮上的命令绑定执行类似的操作:

<Button x:Name="buttonDelete"
        Command="{Binding ElementName="MyItemsControl", Path=DataContext.DeleteItemCommand}"
        CommandParameter="{Binding}"/>