我有一个DataGrid如下:
<DataGrid CanUserAddRows="True" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserDeleteRows="True"
ItemsSource="{Binding Groups}" AutoGenerateColumns="False">
<DataGrid.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"/>
</DataGrid.InputBindings>
<DataGrid.Resources>
<CompositeCollection x:Key="Items">
<ComboBoxItem IsEnabled="False" Background="#FF2A2A2A" Foreground="White">
<Grid TextElement.FontWeight="Bold" >
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition Width="50" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="Group Name" />
<TextBlock Grid.Column="2" Text="Effect" />
</Grid.Children>
</Grid>
</ComboBoxItem>
<CollectionContainer Collection="{Binding Source={StaticResource GroupNamesWithCorrespondingEffectsCollection}}" />
</CompositeCollection>
<DataTemplate DataType="{x:Type helpers:GroupNameWithCorrespondingEffect}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition Width="50" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="{Binding GroupName}" />
<TextBlock Grid.Column="2" Text="{Binding CorrespondingEffect}" />
</Grid.Children>
</Grid>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding GroupName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Group" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{DynamicResource Items}"
SelectedValue="{Binding ParentID}"
SelectedValuePath="GroupID" Grid.IsSharedSizeScope="True" TextSearch.TextPath="GroupName">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Effect" Width="*" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.Effects, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" DisplayMemberPath="Effect"
SelectedValue="{Binding EffectID}" SelectedValuePath="EffectID"
Visibility="{Binding Path=DataContext.SelectedGroupID,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
Converter={StaticResource effectsVisibilityConverter}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
以下是我的Page的DataContext绑定到的GroupsViewModel:
public class GroupsViewModel : ViewModelBase
{
public GroupsViewModel()
{
Groups = new ObservableCollection<Group>();
NewRowCommand = new RelayCommand(NewRow);
using (Entities db = new Entities())
{
List<GroupNameWithCorrespondingEffect> _GroupNamesWithCorrespondingEffects = (
from g in db.Groups
select new GroupNameWithCorrespondingEffect
{
GroupID = g.GroupID,
GroupName = g.GroupName,
CorrespondingEffect = g.Master_Effects.Effect
}
).ToList();
GroupNamesWithCorrespondingEffects
= new ObservableCollection<GroupNameWithCorrespondingEffect>(
_GroupNamesWithCorrespondingEffects.Where
(
u => !StaticMethods.GetAllChildren(25)
.Select(x => x.GroupID)
.Contains(u.GroupID)
).ToList()
);
Effects = new ObservableCollection<Master_Effects>(from m in db.Master_Effects
select m);
}
}
private ObservableCollection<Group> _groups;
public ObservableCollection<Group> Groups
{
get
{
return _groups;
}
set
{
_groups = value;
OnPropertyChanged("Groups");
}
}
public ICommand NewRowCommand { get; set; }
private void NewRow(object obj)
{
Groups.Add(new Group());
}
}
问题:
我在datagrid中输入一些数据,然后按 Enter 添加一个新行到datagrid,这是预期的。但是新行被添加到DataGrid的顶部,而我希望它在最后位置添加。其他行中的数据也被清除,但我希望它是原样的。
答案 0 :(得分:1)
CanUserAddRows会引起一些混乱吗?
“当此属性设置为true时,DataGrid底部会显示一个空行。”
此行将始终位于ObservableCollection提供的行下方。我把一些虚拟数据放入NewRole,如下所示:
var p = new Person() {Name = "New " + DateTime.Now.TimeOfDay.TotalMilliseconds};
People.Add(p);
使结果更清晰一点。添加几行时,TotalMilliseconds的最大值将位于集合的末尾,并且将是DataGrid中的倒数第二行。
答案 1 :(得分:0)
罪魁祸首是你的KeyBinding
。根据您的示例项目,当您按Enter键时,永远不会将DataGrid
中的值保存回集合中。它通常在失去焦点时发生,但由于 Enter 在焦点丢失之前添加了一行,因此在空集合中添加一个空行。
DataGrid
检测到更改并使用此新行更新视图,同时保留正在进行的更改(您按下的行 Enter 还没有完成更新) 。结果显然是你所看到的。
我不确定您为什么要使用 Enter 作为KeyBinding
来添加行,这应该是自己发生的?如果它没有发生,那是因为DataGrid
无法创建您的模型(也许它不公开?或者您可能没有定义默认的无参数ctor ?)
对于您的示例项目,我删除了您的KeyBinding
&amp;在您的Person模型上实现INotifyChanged
并且它可以正常工作。
如果你正在使用CellTemplates,你也需要实现CellEditingTemplate。
<DataGrid CanUserAddRows="True" CanUserDeleteRows="True" CanUserReorderColumns="False" CanUserResizeColumns="False" AutoGenerateColumns="False" ItemsSource="{Binding People}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Age" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>