如何将行动态添加到 UWP 中的数据网格?
How to add rows dynamically to a Datagrid in UWP?
我正在尝试准确实现在 Microsoft Access 中可以看到的内容,目前我使用的是 Datagrid,但我不确定这是完成这项工作的正确工具。
当您查看屏幕截图时,最后一行始终为空,您可以添加任何内容;如果您删除其中一行,所有接下来的行都会在索引中上升,并且一切都非常顺利。
如何在 UWP 中完成?我是否必须从头开始编写所有逻辑,或者是否有一些控件可以帮助实现这一点?
目前,我的想法是我必须检查所有单元格的内容,如果一个单元格为空,则手动将它们向上移动,然后创建一个“假”行,其中包含一个包含“添加行”内容的占位符文本框当您在上面书写时,它会自动更改,因为它会在下面创建一个额外的行。
所有这些还需要移动绑定集合中的项目,我已经可以看到噩梦般的结果。我走在正确的道路上吗?
我的另一个想法是在所有行中包含一个“删除行”按钮,该按钮将从集合中删除该行,这将通过绑定自动更新。只需在其下添加一个“添加行”,即可在绑定集合中创建一个空对象,然后用户将对其进行编辑。它会更流畅,但也感觉像一个 hack,而且到处都是所有“删除行”按钮仍然不是那么流畅。
DataGrid
中没有API可以直接实现你想要的。在DataGrid
中添加“删除行”按钮的想法是可行的,您可以参考下面的代码来解决您的问题。
DataGrid
使用双向绑定。在数据源的最后一项中,PersonId
设置为“[Add New Row]”,其他所有属性为空。
- 在
EmployeeGrid_BeginningEdit
事件中,编辑DataGrid
的最后一行时,将向数据源中插入一个具有空属性的实例。
- 在
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));
}
}
}
结果:
我正在尝试准确实现在 Microsoft Access 中可以看到的内容,目前我使用的是 Datagrid,但我不确定这是完成这项工作的正确工具。
当您查看屏幕截图时,最后一行始终为空,您可以添加任何内容;如果您删除其中一行,所有接下来的行都会在索引中上升,并且一切都非常顺利。
如何在 UWP 中完成?我是否必须从头开始编写所有逻辑,或者是否有一些控件可以帮助实现这一点?
目前,我的想法是我必须检查所有单元格的内容,如果一个单元格为空,则手动将它们向上移动,然后创建一个“假”行,其中包含一个包含“添加行”内容的占位符文本框当您在上面书写时,它会自动更改,因为它会在下面创建一个额外的行。
所有这些还需要移动绑定集合中的项目,我已经可以看到噩梦般的结果。我走在正确的道路上吗?
我的另一个想法是在所有行中包含一个“删除行”按钮,该按钮将从集合中删除该行,这将通过绑定自动更新。只需在其下添加一个“添加行”,即可在绑定集合中创建一个空对象,然后用户将对其进行编辑。它会更流畅,但也感觉像一个 hack,而且到处都是所有“删除行”按钮仍然不是那么流畅。
DataGrid
中没有API可以直接实现你想要的。在DataGrid
中添加“删除行”按钮的想法是可行的,您可以参考下面的代码来解决您的问题。
DataGrid
使用双向绑定。在数据源的最后一项中,PersonId
设置为“[Add New Row]”,其他所有属性为空。- 在
EmployeeGrid_BeginningEdit
事件中,编辑DataGrid
的最后一行时,将向数据源中插入一个具有空属性的实例。 - 在
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));
}
}
}
结果: