【问题标题】:How do I get the "selected" instance of an ItemsControl DataTemplate?如何获取 ItemsControl DataTemplate 的“选定”实例?
【发布时间】:2015-09-14 03:59:57
【问题描述】:

我创建了一个动态表单,允许用户使用 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;
        }
    }
}

【问题讨论】:

  • 尝试获取网格选中的行索引并删除
  • Variation 项目类应该公开一个删除命令,从FormItem.Variations 集合中删除它。您可以将 Button 的 Command 属性绑定到 Delete 命令,而不是使用 Button Click 处理程序。
  • @Clemens:谢谢。你让我走上了正确的道路。该命令只能在 FormItem.Variations 类中访问,但问题是我的 Variations 类嵌套在 Item 类中,因此我无法访问 Variations 集合以从中删除变体,除非它是静态的,这是不可能的在我的情况下,因为每个项目都需要自己的 Variations 集合。我似乎找不到方法。我已将我的 Item 类代码添加到帖子中。

标签: c# xaml data-binding windows-runtime windows-8.1


【解决方案1】:

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

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

你可以对删除按钮上的命令绑定做这样的事情:

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

【讨论】:

  • 除了Mode=FindAncestor 在 Windows 运行时不可用。我建议用 ElementName 绑定替换它。此外,该命令可能会移动到 FormItem 类(它包含 Variations 属性),因此路径将是 Path=DataContext.FormItem.DeleteItemCommand
  • 没有意识到 FindAncestor 模式在 Windows 运行时中不起作用。我会相应地更新我的答案。
  • 克莱门斯,非常感谢!谢谢你碎石。它现在正在工作。
猜你喜欢
  • 2011-01-21
  • 2011-06-12
  • 2015-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多