Xamarin:如何删除网格中特定行中的项目

Posted

技术标签:

【中文标题】Xamarin:如何删除网格中特定行中的项目【英文标题】:Xamarin: How to remove an item in a specific row in Grid 【发布时间】:2022-01-02 10:16:44 【问题描述】:

我有一个网格,我正在尝试删除特定行中的项目。它在一个循环中,然后当它转到第二行时,它会删除第二行中的项目,并删除第一行中的项目。如何调整以仅删除我想要的行?

请注意,我要做的是将第一行复制到第二行,仅解决 pow (b²),在第三行中我将复制第二行,但解决 -4 * 5 (-4 *一)。

这是正在发生的事情的预览。

This 是我扩充这些行的代码,以了解: 它首先进入if(fields == null),因为是pow,然后进入else

for (int i = 0; i < qntLines; i++)

   string field = lines[i].Substring(0, lines[i].IndexOf('#'));
   string operation = lines[i].Substring(lines[i].IndexOf('#') + "#".Length);

   CreateResultLine(field, operation, i, listTexts);


private void CreateResultLine(string field, string operation, int i, List<string> listTexts)

            string[] fields = null;
            List<string> texts = new List<string>();
            string text = string.Empty;
            dynamic textResult;
            int count = new int();

            if (field.Contains(','))
                fields = field.Split(',', (char)StringSplitOptions.RemoveEmptyEntries);
            
            if (fields == null)
            
                text = listTexts[int.Parse(field)];
                text = RemovePow(text);
                texts.Add(text);
                textResult = ExecuteOperation(texts, operation);
                
                gridFrame.Children.RemoveAt(int.Parse(field) + 1);
                gridFrame.Children.Add(new Label()  Text = textResult.ToString(), HorizontalTextAlignment = TextAlignment.Center, 
                    TextColor = Color.Blue, HorizontalOptions = LayoutOptions.Center , int.Parse(field) + 1, i);
            
            else
            
                foreach (var item in fields)
                
                    string noPow = string.Empty;
                    noPow = RemovePow(listTexts[int.Parse(item)]);
                    texts.Add(noPow);
                    ++count;
                
                textResult = ExecuteOperation(texts, operation);

                for (int i2 = int.Parse(fields[0]); i2 <= int.Parse(fields[1]);)
                
                    gridFrame.Children.RemoveAt(int.Parse(fields[0]));
                    
                    ++i2;
                

                gridFrame.Children.Add(new Label()  Text = textResult.ToString(), HorizontalTextAlignment = TextAlignment.Center, 
                    TextColor = Color.Blue, HorizontalOptions = LayoutOptions.Center , int.Parse(fields[0]) + 1, i);
            
        

【问题讨论】:

我没有研究过你的代码,但我会做一个一般性的评论:与其试图操纵gridFrame.Children,为什么不简单地设置someItem.IsVisible = false;,其中someItem是网格单元格你想隐藏吗?然后为了显示不同的结果,有一个不同的项目,IsVisible = false 开头,更新它的文本,然后设置它的IsVisible=true。对我来说,操纵视图的可见性比按摩布局的子级更容易。 另一个想法:当你创建每个项目时,如果你以后需要访问它,然后以某种方式“记住”它。如果在 xaml 中创建了一个网格行,您可以给它一个 x:name 属性。如果在 c# 中创建了一个网格行,那么您可以使用您想要记住的那些创建一个列表字段(因此很容易知道正确的索引),或者您可以使用给定的键添加到字典中,以找到它稍后通过键字符串。无论哪种方式,您都不再需要 循环 遍历孩子。您直接转到您关心的项目。 现在看看你的代码有什么问题。我不打算详细阅读,但有一个事实让我眼前一亮。当您执行多个RemoveAts 时,一旦删除第一个,就会更改所有索引以供以后使用RemoveAts。一种解决方法:“最后一个”删除它们。一种方法是反转循环:从最高索引开始并使用递减--。 (而不是从具有增量的最低索引开始。)另一种解决方案是,当您找到要删除的每个项目时,不要删除它。将其放入“toRemove”列表中。然后,当您找到所有这些时,在每个上使用 Remove 对于您的最后一条评论,您能给我看一些代码示例吗?我不明白我怎么能像你说的那样做。 我添加了一个答案,显示了更好的方法。 【参考方案1】:

这是一个使用网格单元格的完整示例。

这个概念是您首先创建所有单元格。在这里,我在每个网格单元格中使用Label。为了更容易理解,我将每个单元格的文本设置为我分配给它的“CellNumber”。一旦你明白发生了什么,只需将一个空字符串"" 作为初始值。

为了方便查找单元格,Dictionary 包含它们。 CellNumber(row, column)key 提供给该字典,以查找相应的单元格。

Calculate 按钮对单元格进行了一些更改,因此您可以了解如何操作。

一旦初始化,我建议不要添加或删除单元格(网格的孩子)。相反,显示或隐藏一个单元格。在这里,您可以通过更改 LabelText 来做到这一点。对于其他类型的Views,您可以将View.IsVisible 更改为true 或false。

MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ManipulateGridChildren.MainPage">

    <Grid x:Name="Formulas" BackgroundColor="#A0A0A0"
          RowSpacing="2" ColumnSpacing="2" Padding="2"
          ColumnDefinitions="*,*,*,*,*,*,*,*"
          RowDefinitions="40,40,40,Auto">
        <Button Grid.Row="3" Text="Calc" Command="Binding CalcCommand" />
    </Grid>

</ContentPage>

MainPage.xaml.cs:

using System.Collections.Generic;
using Xamarin.Forms;

namespace ManipulateGridChildren

    public partial class MainPage : ContentPage
    
        const int NRows = 3;
        static int NColumns = 8;
        const int MaxColumns = 100;

        private Dictionary<int, Label> cells = new Dictionary<int, Label>();

        public MainPage()
        
            InitializeComponent();
            AddCells();
            CalcCommand = new Command(Calculate);
            BindingContext = this;
        

        public Command CalcCommand  get; set; 

        private void Calculate()
        
            SetCellText(0, 0, "A");
            SetCellText(0, 2, "B");
            SetCellText(1, 0, "C");
            SetCellText(2, 3, "D");
            SetCellBackground(2, 3, Color.Pink)
        

        private void SetCellText(int row, int column, string text)
        
            cells[CellNumber(row, column)].Text = text;
        

        private void SetCellBackground(int row, int column, Color color)
        
            cells[CellNumber(row, column)].BackgroundColor = color;
        

        private void AddCells()
        
            // Grid rows and columns are numbered from "0".
            for (int row = 0; row < NRows; row++) 
                for (int column = 0; column < NColumns; column++) 
                    var cell = AddCell(row, column);
                    cells[CellNumber(row, column)] = cell;
                
            

            // Add "frames" around some rows.
            // AFTER adding the cells, so drawn on top.
            AddFrame(0, 1, 0, NColumns);
            AddFrame(1, 2, 0, NColumns);
        

        private Label AddCell(int row, int column)
        
            var cell = new Label();
            // For debugging - show where each cell is.
            // Once you understand, change this to an empty string.
            cell.Text = $"CellNumber(row, column)";
            cell.BackgroundColor = Color.White;
            cell.HorizontalTextAlignment = TextAlignment.Center;
            cell.VerticalTextAlignment = TextAlignment.Center;
            Formulas.Children.Add(cell, column, row);
            return cell;
        

        // Assign unique number to each cell.
        private int CellNumber(int row, int column)
        
            return row * MaxColumns + column;
        

        private void AddFrame(int row, int rowSpan, int column, int columnSpan)
        
            var rect = new Xamarin.Forms.Shapes.Rectangle 
                Stroke = new SolidColorBrush(Color.Black),
                StrokeThickness = 2
            ;

            Formulas.Children.Add(rect, column, column + columnSpan, row, row + rowSpan);
        
    

【讨论】:

谢谢,我按照这个想法创建了一个网格列表,然后只显示它是否可见。【参考方案2】:

对你想要达到的目标有点困惑,但这里有一个建议。

我建议采用 MVVM 模式。在代码中操作 UI 并不是最好的主意。

<ContentPage.BindingContext>
   <local: MainViewModel />
</ContentPage.BindingContext>

<ContentPage.Content>

  <ListView ItemSource=Binding ListOfItems>
     <ListView.ItemTemplate>
       <DataTemplate>
          <ViewCell>
             <Label Text=Binding ./>
          <ViewCell>
       </DataTemplate>
     </ListView.ItemTemplate>
  </ListView>
</ContentPage.Content>

MainViewModel.cs

public class MainViewModel : INotifyPropertyChanged


public ObservableCollection<string> ListOfItems get;set; = new ObservableCollection<string>();

public void DeleteAnItem(string s)

  ListOfItems.Remove(s);


public void AddItem(string s)

 ListOfItems.Add(s);


public void RemoveAtIndex(int i)

  ListOfItems.RemoveAt(i);


#region TheRestOfPropertyChanged
...
#endregion

您对列表所做的每项更改都将在您的 UI 中显示。

【讨论】:

以上是关于Xamarin:如何删除网格中特定行中的项目的主要内容,如果未能解决你的问题,请参考以下文章

如何删除文件中某些行中的特定字符?

ExtJS 4 - 如何禁用特定行中的复选框

如何删除 Material UI DataGrid (Reactjs) 中的特定行

ExtJS 3:如何根据行中的值对不同的行定义不同的操作?

单击 CursorAdapter 中的按钮时如何在列表视图项目行中执行更新和删除操作

如何在顺风中以自定义高度居中网格行中的元素?