【问题标题】:I need to Delete a Control inside a WrapPanel created dynamically inside another WrapPanel while in Run-Time我需要在运行时删除在另一个 WrapPanel 内动态创建的 WrapPanel 内的控件
【发布时间】:2020-01-06 19:16:40
【问题描述】:

所以,我有一个名为“valoresPanel”的主要WrapPanel。当我开始运行时,我需要单击标记为“2”的Button(如下),并且TextBox 需要出现在标记为“1”的WrapPanel 中,这是在运行时创建的。

这是我现在的“+按钮”代码:

void novoValor_Click(object sender, RoutedEventArgs e)
       {
           WrapPanel wpValores = new WrapPanel();

           Button deleteValor = new Button();
           TextBox txtValor = new TextBox();

           deleteValor.Height = 25;
           deleteValor.Width = 25;
           deleteValor.Content = "X";

           txtValor.Height = 25;
           txtValor.Width = 70;
           txtValor.Margin = new Thickness(0, 0, 8, 0);

           wpValores.Height = 25;
           wpValores.Width = 105;

           wpValores.Children.Add(deleteValor);
           wpValores.Children.Add(txtValor);

           valoresPanel.Children.Add(wpValores);

           deleteValor.Click += deleteValor2_Click;
       }  

所以,我更新了我的代码,每个项目只使用一个 WrapPanel,现在我可以添加一个项目,添加值并删除具有各自值的项目,但我不能删除特定值,这是我现在的代码:

this image will help to understand

 void novoValor_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            WrapPanel wpFather = btn.Parent as WrapPanel;
            WrapPanel wpValue = new WrapPanel();

            Button deleteValue = new Button();
            TextBox txtValue = new TextBox();

            wpValue.Height = 25;
            wpValue.Width = 105;

            deleteValue.Height = 25;
            deleteValue.Width = 25;
            deleteValue.Content = "-";

            txtValue.Height = 25;
            txtValue.Width = 70;
            txtValue.Margin = new Thickness(0, 0, 8, 0);

            wpValue.Children.Add(deleteValue);
            wpValue.Children.Add(txtValue);

            wpFather.Children.Add(wpValue);

            deleteValue.Click += deleteValor_Click;
        }

        void deleteValor_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            WrapPanel panel = btn.Parent as WrapPanel;
            entradasPanel.Children.Remove(panel);
        }

如果有人需要任何其他信息,我愿意尽快发送!

【问题讨论】:

  • 那么,您到底遇到了什么问题?什么不工作?
  • valoresPanel 的宽度似乎是有限的,否则你添加到它的孩子应该放在右边,而不是像你的图片那样在它下面。什么包含valoresPanel?我们真的需要看看整个视觉树是什么样子的。您能否使用可视化树中实际存在的所有元素创建一个展示问题的 XAML 表示形式?
  • 你对TextBox元素的输入做了什么?如何得到它?您的 C# 方法是错误的。您应该创建一个ListView,它的WrapPanelItemsPanel。然后到ListView.ItemsSource 绑定一个ObservableCollection 的数据模型。通过为ListView.ItemTemplate 定义DataTemplate,您可以使数据项显示为带有ButtonTextBox,其中TextBox 绑定到此项的数据模型。通过按删除按钮,您只需从ObservaleColectionItemsSourceListView)中删除此数据模型。
  • @andrew 这是因为我使用所有行空间创建了一个 WrapPanel,如果我减小宽度,新的子项将出现在右侧,但是当我单击第一个“x”时我需要它清理第一个“Entrada”及其所有值(“valores”)。
  • @KeithStein 我需要创建一个新的“entrada”,并为其各自的值(“valores”)留出空间,当我单击第一个“X”按钮时,我需要它来清理“entrada”空间及其所有各自的“价值”。

标签: c# wpf wpf-controls


【解决方案1】:

您应该创建一个ListView,其中有一个WrapPanel 作为ItemsPanel。然后到ListView.ItemsSource 绑定一个ObservableCollection 的数据模型。通过为ListView.ItemTemplate 定义DataTemplate,您可以使数据项显示为带有ButtonTextBox,其中TextBox 绑定到该项的数据模型。通过按下删除按钮,您只需从ObservaleColectionListViewItemsSource)中删除此数据模型。

DataModel.cs

class DataModel
{
  public string UserInput { get; set; }
}

ViewModel.cs

class ViewModel
{
  public ObservableCollection<DataModel> Items { get; set; }
  public ICommand AddItemCommand => new AsyncRelayCommand(() => this.Items.Add(new DataModel()));    
  public ICommand RemoveItemCommand => new AsyncRelayCommand((item) => this.Items.Remove(item));

  public ViewModel()
  {
    this.Items = new ObservableCollection<DataModel>();
  }
}

MainWindow.xaml

<Window>
  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

  <StackPanel>
    <Button Content="Add Item"
            Command="{Binding AddItemCommand}" />

    <ListView ItemsSource="{Binding Items}">
      <ListView.ItemsPanel>
        <ItemsPanelTemplate>
          <WrapPanel Width="600" />
        </ItemsPanelTemplate>
      </ListView.ItemsPanel>

      <ListView.ItemTemplate>
        <DataTemplate DataType="{x:Type DataModel}">
          <StackPanel Orientation="Horizontal">
            <Button Content="Remove Item"
                    Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}, Path=DataContext.RemoveItemCommand}"
                    CommandParameter="{Binding}" />
            <TextBox Text="{Binding UserInput}" />
          </StackPanel>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </StackPanel>
</Window>

【讨论】:

  • 所以,我更新了我的代码,每个项目只使用了一个 WrapPanel,现在我可以添加一个项目,添加值和删除项目及其各自的值,但我不能删除一个特定的值,我会更新我的新值上面的代码,感谢您的回复,我稍后再试。
  • 好的。但是,如果您更喜欢更简洁的解决方案,即在视图模型中处理数据操作(而不是在视图的代码隐藏中)并使用数据绑定来检索TextBox 的内容,请考虑我的解决方案。这是一种简单而干净的 XAML 方法。使用 XAML 创建控件是首选和推荐的方式。
  • 所以,我试图应用您的解决方案,但由于我使用 WPF,因此使用此代码时出现了一些错误消息,例如 ViewModel 和 DataItem 不受支持..
  • 你必须实现类。看我的例子。 ViewModel 是一个类。 DataModel 也是如此。 DataItemDataType 是一个错字,而是 DataModel。我更正了。
  • 您可以复制并粘贴它,它应该可以工作。您可能需要实现自己的ICommand 或下载AsyncRelayCommand,方法是通过右键单击引用此类的项目选择“NuGet 包管理器”。然后搜索“AsyncRelayCommand”。
【解决方案2】:

我可以用以下代码解决我的最后一个问题:

    void deleteValue_Click(object sender, RoutedEventArgs e)
    {
        Button btn = sender as Button;
        WrapPanel panel = btn.Parent as WrapPanel;
        WrapPanel panelPai = panel.Parent as WrapPanel;
        panelPai.Children.Remove(panel);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 2011-10-24
    • 1970-01-01
    • 2011-06-07
    相关资源
    最近更新 更多