【问题标题】:Dynamically Add and Remove stack panel动态添加和删除堆栈面板
【发布时间】:2011-04-26 13:42:55
【问题描述】:

我在ListBox(灰色背景)中有一个WrapPanel(绿色背景)。

我正在尝试在WrapPanel 中多次动态添加StackPanel(通过单击给定图像下方的按钮)。

StackPanel 包含一个 Button,其内容为“X”。单击此按钮时,我想删除单个 StackPanel 对象(带有橙色背景)。

如何解决?

【问题讨论】:

  • StackPanels 是如何定义的?如果要在代码中动态生成它们,则必须能够获取它们的内容。有很多方法可以做到这一点,但很难说出你在寻找什么。
  • 直截了当......只需通过单击右上角的按钮删除“堆栈面板”......“堆栈面板+按钮”按钮是动态添加的...... .在运行时......

标签: .net wpf stackpanel wrappanel


【解决方案1】:

Data Binding & Data Templating + Commanding

你的问题有点广泛。基本大纲是创建可绑定的集合,数据模板,并使用命令或事件从中删除单击的项目。

使用内部使用 WrapPanel 进行布局的 ItemsControl 的 DataTemplating 示例:

<ItemsControl ItemsSource="{Binding DpData}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <!-- The content goes here, X-Button will be overlayed -->
                <Button HorizontalAlignment="Right"
                        VerticalAlignment="Top"
                        Content="X" Click="RemoveItem_Click"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
// Does not need to be a dependency property.
public static readonly DependencyProperty DpDataProperty =
    DependencyProperty.Register("DpData", typeof(ObservableCollection<Employee>), typeof(MainWindow), new UIPropertyMetadata(new ObservableCollection<Employee>()));
public ObservableCollection<Employee> DpData
{
    get { return (ObservableCollection<Employee>)GetValue(DpDataProperty); }
    set { SetValue(DpDataProperty, value); }
}
// For simplicity i use an event instead of a command.
private void RemoveItem_Click(object sender, RoutedEventArgs e)
{
    var button = (FrameworkElement)sender;
    var emp = (Employee)button.DataContext;
    DpData.Remove(emp);
}

如果您这样做,您当然不应该在单击添加按钮时添加面板,而是将数据项添加到集合中。面板会自动生成。

【讨论】:

  • 其实我是 WPF 新手,所以...你能告诉我...如何在 ListBox 中使用
  • 你可以像添加环绕面板一样添加它,它基本上扩展了环绕面板。
  • @H.B,在这里,...尽可能多的“Employee”实例我将存储在“DpData”中...在运行时我将在 上看到多少按钮....是对还是错?
  • 将为列表中的每个元素 (DpData) 创建一个模板,每个模板都包含一个按钮。
  • @H.B,你好 H.B 感谢您的回复....在这里,我已将上述 XAML 代码放在我的“mainwindow.xaml”和“DpData”属性以及“DpDataProperty”中的“mainwindow.xaml”中。 cs”....在“mainWindow_Loaded”事件中,我将代码放在下面 [ DpData.Add(new Employee("pritesh0", "abad0", 22)); ] ....问题是虽然我没有在ItemControl中得到“BUTTON”........谢谢............
【解决方案2】:

这是最终代码............

MainWindow.xaml

<Window.Resources>
    <DataTemplate x:Key="itemsTemplate">
        <!-- This might also be included in a UserControl -->
        <Border Width="200" Height="200" CornerRadius="10,10,10,10" Margin="4,4,0,0" Padding="4,4,4,4">
            <Border.Background>
                <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                    <GradientStop Color="AliceBlue" Offset="0"/>
                    <GradientStop Color="Bisque" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background>
            <Grid >
                <Button HorizontalAlignment="Right" VerticalAlignment="Top" Width="30" Height="20"  Content="X" Background="Red" Click="Remove_Click"></Button>
                <WrapPanel Orientation="Vertical">
                <TextBox Text="{Binding Name}" Margin="10,10" Height="20"  ></TextBox>
                    <TextBox Text="{Binding City}" Margin="10,10" Height="20" ></TextBox>
                    <TextBox Text="{Binding Age}" Margin="10,10" Height="20"></TextBox>
                    <TextBox Text="{Binding Count}" Margin="10,10" Height="20" ></TextBox>
                </WrapPanel>
            </Grid>
        </Border>
    </DataTemplate>
</Window.Resources>
<Grid>
    <ItemsControl 

              Width="Auto"
              Height="Auto"
              ItemsSource="{Binding ElementName=mainWindow, Path=EmployeeCollection}"
              ItemTemplate="{StaticResource itemsTemplate}"  Background="Aqua">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Vertical" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
    <Button Content="Add" Height="23" HorizontalAlignment="Left" Margin="487,287,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="Add_Click" />
</Grid>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace DynamicAddRemovePanel
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<Employee> employeeCollection = new ObservableCollection<Employee>();

        public ObservableCollection<Employee> EmployeeCollection
        {
            get
            {
                return this.employeeCollection;
            }
            set
            {
                this.employeeCollection = value;
            }
        }
        public MainWindow()
        {
            InitializeComponent();
        }




        public class Employee
        {
            public string Name { get; set; }
            public string City { get; set; }
            public int Age { get; set; }
            public static int Count { get; set; }
            public Employee()
            {
                Count++;
            }
            public Employee(string nameArg, string cityArg, int ageArg)
            {
                this.Name = nameArg;
                this.City = cityArg;
                this.Age = ageArg;
                Count++;
           }
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            employeeCollection.Add(new Employee("Pritesh","Abad",22));
        }
        private void Remove_Click(object sender, RoutedEventArgs e)
        {
            var emp = (sender as FrameworkElement).DataContext as Employee;
            employeeCollection.Remove(emp);
        }


    }
}

【讨论】:

  • 把这些放在一起做得很好;只是对您的成员声明的一些建议:对于集合,您通常不提供公共 set 访问器,因为您可以清除它们,进一步您将设置字段 readonly 以防止它在内部被覆盖,这是因为如果您这样做,绑定将中断(绑定控件仍然监视不再使用且代码中不再存在引用的对象)。此外,如果您更改其他属性并希望更新 UI,则需要在其所属类中实现 INotifyPropertyChanged
  • @H.B,非常感谢您的建议......我会记住所有这些事情......在这里我没有因为这一切而烦恼....我是以输出为导向的......谢谢......
  • 注意:不要忘记在 中添加 x:Name="mainWindow" 因为我们有在 ItemControl 的 ItemSource 属性中使用它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多