在运行时添加和删除网格行

时间:2019-01-27 14:44:09

标签: c# uwp uwp-xaml

我正在尝试使用网格创建一个布局,在该布局中,您有一个“ +”按钮来添加新行以输入内容,并在每个新行旁边添加“-”按钮以删除该行。

example image

我已经遍地搜索,在运行时删除XAML网格行上方没有发现任何事情。

启动时的静态布局:

<Grid Grid.Row="0" Margin="0" VerticalAlignment="Top" Name="GridSource">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="75" />
        <ColumnDefinition Width="150" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Column="0" Grid.Row="0" Name="lblSource0" Text="Source:" Margin="5" />
    <ComboBox Grid.Column="1" Grid.Row="0" Name="cmboSource0" Margin="5" SelectionChanged="CmboSource_SelectionChanged" />
    <TextBox Grid.Column="2" Grid.Row="0" Name="txtSource0" TextWrapping="NoWrap" Margin="5" IsReadOnly="True" />
    <Button Grid.Column="3" Grid.Row="0" Name="btnSource0" Content="..." Width="50" Margin="5" />
    <Button Grid.Column="4" Grid.Row="1" Name="btnAddSource" Content="+" Width="50" Margin="5" Click="BtnAddSource_Click" Height="32" />
</Grid>

添加和删除行的逻辑:

private void BtnAddSource_Click(object sender, RoutedEventArgs e)
{
    AdditionalSourceCounter++;
    string Name = "Source" + AdditionalSourceCounter.ToString();
    GridSource.RowDefinitions.Add(new RowDefinition()); //add new row to Grid
    Grid.SetRow(btnAddSource, GridSource.RowDefinitions.Count); //move "add Source"-button to last row

    TextBlock newLabel = new TextBlock();
    newLabel.Name = "lbl" + Name;
    newLabel.Text = "Source:";
    newLabel.Margin = new Thickness(5);
    GridSource.Children.Add(newLabel); //add new object to form
    Grid.SetColumn(newLabel, 0);
    Grid.SetRow(newLabel, AdditionalSourceCounter);

    ComboBox newComboBox = new ComboBox();
    newComboBox.Name = "cmbo" + Name;
    newComboBox.Margin = new Thickness(5);
    GridSource.Children.Add(newComboBox); //add new object to form
    for (int i = 0; i < Data.SourceTypes.Count; i++) //add items from SourceTypes-list to ComboBox
        newComboBox.Items.Add(Data.SourceTypes[i]);
    newComboBox.SelectedIndex = 0;
    newComboBox.SelectionChanged += CmboSource_SelectionChanged;
    Grid.SetColumn(newComboBox, 1);
    Grid.SetRow(newComboBox, AdditionalSourceCounter);

    TextBox newTextBox = new TextBox();
    newTextBox.Name = "txt" + Name;
    newTextBox.TextWrapping = TextWrapping.NoWrap;
    newTextBox.Margin = new Thickness(5);
    newTextBox.IsReadOnly = true;
    GridSource.Children.Add(newTextBox); //add new object to form
    Grid.SetColumn(newTextBox, 2);
    Grid.SetRow(newTextBox, AdditionalSourceCounter);

    Button newButton = new Button();
    newButton.Name = "btn" + Name;
    newButton.Content = "...";
    newButton.Width = 50;
    newButton.Margin = new Thickness(5);
    GridSource.Children.Add(newButton); //add new object to form
    Grid.SetColumn(newButton, 3);
    Grid.SetRow(newButton, AdditionalSourceCounter);

    Button newButtonRemove = new Button();
    newButtonRemove.Name = "btnRemove" + Name;
    newButtonRemove.Content = "-";
    newButtonRemove.Width = 50;
    newButtonRemove.Margin = new Thickness(5);
    newButtonRemove.Click += BtnRemoveSource_Click;
    GridSource.Children.Add(newButtonRemove); //add new object to form
    Grid.SetColumn(newButtonRemove, 4);
    Grid.SetRow(newButtonRemove, AdditionalSourceCounter);
}

private void BtnRemoveSource_Click(object sender, RoutedEventArgs e)
{
    AdditionalSourceCounter--;
    var callingButton = (Button)sender;
    int rowNumber = Grid.GetRow(callingButton);
    int callingButtonIndex = GridSource.Children.IndexOf(callingButton);
    GridSource.Children.RemoveAt(callingButtonIndex);
    GridSource.Children.RemoveAt(callingButtonIndex - 1);
    GridSource.Children.RemoveAt(callingButtonIndex - 2);
    GridSource.Children.RemoveAt(callingButtonIndex - 3);
    GridSource.Children.RemoveAt(callingButtonIndex - 4);
    GridSource.RowDefinitions.RemoveAt(rowNumber);
    Grid.SetRow(btnAddSource, GridSource.RowDefinitions.Count);
}

添加行是可行的,但是删除行则具有...有趣的结果。首先最明显的是“ +”按钮覆盖了最后的“-”按钮,因此整个事情变得不可用了,我也不知道为什么... 目标是布局保持与上面的屏幕快照相同,因此您可以在任意位置添加和删除行。

1 个答案:

答案 0 :(得分:2)

您正在将添加按钮的行设置为GROUP BY IDEA.I_ID,IDEA.I_NO,IDEA.I_TITLE,IDEA.I_DESCRIPITION,IDEA.I_CREATED_DATE,STATUS.S_DESCRIPTION,APPL_USER.U_NAME; 。但是,这比GridSource.RowDefinitions.Count中实际存在的行数多一。行从0到Grid进行计数,因此最后一行是Count - 1。发生的情况是GridSource.RowDefinitions.Count-1找不到索引为Grid的行,因此仅将按钮放在行Count中,因此该按钮覆盖了最后一行的Count-1按钮

如果您检查静态代码,则可以看到仅对加号按钮有另外一行。您也必须在这里复制它。

此外,如果您在-的中间删除一行,则可以正确删除其项目,但还需要将所有下一个元素向上移动一行-因此,您需要减少其Grid属性一个。

Grid.Row

请注意,您可能会考虑使用private void BtnRemoveSource_Click(object sender, RoutedEventArgs e) { AdditionalSourceCounter--; var callingButton = (Button)sender; int rowNumber = Grid.GetRow(callingButton); int callingButtonIndex = GridSource.Children.IndexOf(callingButton); foreach ( var child in GridSource.Children.ToArray() ) { var childRow = (int)child.GetValue(Grid.RowProperty); if (childRow == rowNumber) { //this child should be removed GridSource.Children.Remove(child); } else if (childRow > rowNumber) { //move items on next rows one row up child.SetValue(Grid.RowProperty, childRow - 1); } } GridSource.RowDefinitions.RemoveAt(rowNumber); Grid.SetRow(btnAddSource, GridSource.RowDefinitions.Count - 1); } 来代替此冗长且容易出错的代码,其中每个项目都是StackPanel,只有一行,并且各列与您的当前代码匹配-在这种情况下您只需从Grid中删除整个项目,而不必担心固定StackPanel值和Row

甚至更好-您可以使用自定义RowDefinitions将代码重写为ListView