如何将行动态添加到 UWP 中的数据网格?

How to add rows dynamically to a Datagrid in UWP?

我正在尝试准确实现在 Microsoft Access 中可以看到的内容,目前我使用的是 Datagrid,但我不确定这是完成这项工作的正确工具。

当您查看屏幕截图时,最后一行始终为空,您可以添加任何内容;如果您删除其中一行,所有接下来的行都会在索引中上升,并且一切都非常顺利。

如何在 UWP 中完成?我是否必须从头开始编写所有逻辑,或者是否有一些控件可以帮助实现这一点?

目前,我的想法是我必须检查所有单元格的内容,如果一个单元格为空,则手动将它们向上移动,然后创建一个“假”行,其中包含一个包含“添加行”内容的占位符文本框当您在上面书写时,它会自动更改,因为它会在下面创建一个额外的行。

所有这些还需要移动绑定集合中的项目,我已经可以看到噩梦般的结果。我走在正确的道路上吗?

我的另一个想法是在所有行中包含一个“删除行”按钮,该按钮将从集合中删除该行,这将通过绑定自动更新。只需在其下添加一个“添加行”,即可在绑定集合中创建一个空对象,然后用户将对其进行编辑。它会更流畅,但也感觉像一个 hack,而且到处都是所有“删除行”按钮仍然不是那么流畅。

DataGrid中没有API可以直接实现你想要的。在DataGrid中添加“删除行”按钮的想法是可行的,您可以参考下面的代码来解决您的问题。

  1. DataGrid 使用双向绑定。在数据源的最后一项中,PersonId设置为“[Add New Row]”,其他所有属性为空。
  2. EmployeeGrid_BeginningEdit事件中,编辑DataGrid的最后一行时,将向数据源中插入一个具有空属性的实例。
  3. DeleteButton_Click事件中,您可以删除数据源中对应的实例。

XAML:

<Grid>
        <StackPanel>
            <controls:DataGrid
                  x:Name="EmployeeGrid"
                  ItemsSource="{x:Bind Persons,Mode=TwoWay}"
                  AutoGenerateColumns="False"
                 GridLinesVisibility="All"
                Width="700"
                Height="800"
                BeginningEdit="EmployeeGrid_BeginningEdit"
                
                >
                <controls:DataGrid.Columns>
                    <controls:DataGridTextColumn Header="PersonId"
                                             Binding="{Binding PersonId}"/>
                    <controls:DataGridTextColumn Header="First Name"
                                             Binding="{Binding FirstName}"/>
                    <controls:DataGridTextColumn Header="Last Name"
                                             Binding="{Binding LastName}"/>
                    <controls:DataGridTextColumn Header="Position"
                                             Binding="{Binding Position}"/>
                    <controls:DataGridTemplateColumn Header="">
                        <controls:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button x:Name="DeleteButton" Background="#00000000" Click="DeleteButton_Click">
                                    <Image Source="/Assets/IconDelete.png" Height="30" Width="30" Stretch="UniformToFill" />
                                </Button>
                            </DataTemplate>
                        </controls:DataGridTemplateColumn.CellTemplate>
                    </controls:DataGridTemplateColumn>
                </controls:DataGrid.Columns>
            </controls:DataGrid>
        </StackPanel>
</Grid>

后面的代码:

namespace AddRow
{

    public sealed partial class MainPage : Page
    {
        public ObservableCollection<Person> Persons { get; set; }
        public MainPage()
        {
            this.InitializeComponent();
            Persons = new ObservableCollection<Person>()
            {
               new Person
               {
                PersonId = "1", FirstName = "Ronald", LastName = "Rumple",
                Position = "Network Administrator"
               },
               new Person
               {
                PersonId = "2",FirstName = "Brett", LastName = "Banner",
                Position = "Software Developer"
               },
               new Person
               {
                PersonId = "3", FirstName = "Alice", LastName = "Anderson",
                Position = "Accountant"
               },
               new Person
               {
                PersonId = "[Add New Row]", FirstName = null, LastName = null,
                Position = null
               }
            };
        }

  
      

        private void EmployeeGrid_BeginningEdit(object sender, Microsoft.Toolkit.Uwp.UI.Controls.DataGridBeginningEditEventArgs e)
        {
            Person p = new Person
            {
                PersonId = "[Add New Row]",
                FirstName = null,
                LastName = null,
                Position = null
            };
            int x = EmployeeGrid.SelectedIndex;
            int y = Persons.Count;
            if (x + 1 == y)
            {
                Persons.Insert(Persons.Count, p);
            }
        }

        private async void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            Person p = button.DataContext as Person;
            var messageDialog = new ContentDialog()
            {
                Title = "Warning",
                Content = "Are you sure you want to delete?",
                PrimaryButtonText = "Ok",
                CloseButtonText = "Cancel"
            };
            var result = await messageDialog.ShowAsync();
            if (result == ContentDialogResult.Primary)
            {
                Persons.Remove(p);
            }
        }

       
    }
    public class Person:INotifyPropertyChanged
    {
        private string personId;
        private string firstName;
        private string lastName;
        private string position;
        public string PersonId { 
            get 
            {
                return personId;
            } 
            set 
            {
                personId = value;
                RaisePropertyChanged(nameof(PersonId));
            } 
        }
        public string FirstName
        {
            get
            {
                return firstName;
            }
            set
            {
                firstName = value;
                RaisePropertyChanged(nameof(FirstName));
            }
        }
        public string LastName
        {
            get
            {
                return lastName;
            }
            set
            {
                lastName = value;
                RaisePropertyChanged(nameof(LastName));
            }
        }
        public string Position
        {
            get
            {
                return position;
            }
            set
            {
                position = value;
                RaisePropertyChanged(nameof(Position));
            }
        }      

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged([CallerMemberName] string propertyname=null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
        }
    }

}

结果: