gpt4 book ai didi

c# - DataGrid 的意外行为

转载 作者:太空狗 更新时间:2023-10-29 19:38:50 24 4
gpt4 key购买 nike

我有一个非常复杂的问题。我已尝试检查所有内容,并且在这个问题上工作了将近 6 个小时。但是我没有成功解决这个问题。那么,问题来了。

问题:

最初当程序加载时:

enter image description here

当我点击任意行的编辑按钮时:

enter image description here

当我保存该行时:

enter image description here

当我点击具有不同父组的另一行上的编辑按钮时:

enter image description here

XAML 如下所示:

<CollectionViewSource x:Key="GroupsViewSource" Source="{Binding Groups, UpdateSourceTrigger=PropertyChanged}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="GroupName"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<CollectionViewSource x:Key="ParentGroupsViewSource" Source="{Binding ParentGroups}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="GroupName"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>

<DataGrid Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Source={StaticResource GroupsViewSource}}"
SelectedItem="{Binding SelectedGroup}" x:Name="dataGrid"
AutoGenerateColumns="False" CanUserAddRows="False"
SelectionMode="Single" SelectionUnit="FullRow" IsSynchronizedWithCurrentItem="True"
EnableRowVirtualization="False" VirtualizingPanel.IsContainerVirtualizable="False" RowEditEnding="DataGrid_RowEditEnding">

<DataGrid.Resources>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" />
</Style>
</DataGrid.Resources>

<i:Interaction.Triggers>
<i:EventTrigger EventName="RowEditEnding">
<i:InvokeCommandAction Command="{Binding DataGridRowEditEndingCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>

<DataGrid.Columns>

<DataGridTemplateColumn Header="Group Name" Width="*" SortMemberPath="GroupName">
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<Grid IsHitTestVisible="True">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{TemplateBinding Content}"/>
<!--FILTER EXPANDER-->
<Expander Grid.Column="1" IsHitTestVisible="True" VerticalAlignment="Top" Margin="30 0 0 0" ToolTip="Filter">
<Border IsHitTestVisible="True" BorderThickness="1" Margin="-160 5 0 0" MinWidth="200" Height="31" >
<TextBox Text="{Binding DataContext.SearchGroupName, ElementName=uc, UpdateSourceTrigger=PropertyChanged}"
TextChanged="SearchTextBox_TextChanged" ToolTip="Enter Group Name to search" FontSize="16" BorderThickness="1" />
</Border>
</Expander>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>

<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding GroupName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding GroupName}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Parent Group" Width="*" SortMemberPath="ParentID">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ParentID, Converter={StaticResource parentIDToGroupNameConverter}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource ParentGroupsViewSource}}"
DisplayMemberPath="GroupName"
SelectedValue="{Binding ParentID, Converter={StaticResource parentIDToGroupNameConverter}}" SelectedValuePath="GroupName"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Edit" Width="50" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button x:Name="btnEdit" Style="{StaticResource ResourceKey=EditButton}" Height="35" Width="35"
Visibility="{Binding DataContext.IsInEdit,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},
Converter={StaticResource boolToVisibilityInverseConverter}}"
Click="EditButton_Click"
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
<Button x:Name="btnSave" Grid.Row="1" Style="{StaticResource ResourceKey=SaveButton}" Height="35" Width="35"
Visibility="{Binding DataContext.IsInEdit,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},
Converter={StaticResource boolToVisibilityConverter}}"
Click="SaveButton_Click"
Command="{Binding DataContext.SaveCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Delete" Width="70" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button x:Name="btnDelete" Style="{StaticResource ResourceKey=DeleteButton}" Height="35" Width="35"
Visibility="{Binding DataContext.IsInEdit,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},
Converter={StaticResource boolToVisibilityInverseConverter}}"
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
<Button x:Name="btnCancel" Grid.Row="1" Style="{StaticResource ResourceKey=CancelButton}" Height="35" Width="35"
Visibility="{Binding DataContext.IsInEdit,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},
Converter={StaticResource boolToVisibilityConverter}}"
Command="{Binding DataContext.CancelCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
Click="CancelButton_Click"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

</DataGrid.Columns>

</DataGrid>

这是代码隐藏:

public partial class ListView : UserControl
{
ERPLiteDBContext db = new ERPLiteDBContext();

public ListView()
{
InitializeComponent();
}

private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;

if (dep == null)
return;

while (dep != null && !(dep is DataGridCell))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

if (dep is DataGridCell)
{
if (!((DataGridCell)dep).IsReadOnly)
{
if (!((DataGridCell)dep).IsEditing)
e.Handled = true;
}
}

while (dep != null && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

if (dep is DataGridRow)
{
((DataGridRow)dep).IsSelected = true;
}

while (dep != null && !(dep is DataGrid))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

if (dep is DataGrid)
{
((DataGrid)dep).Focus();
}
}

private void EditButton_Click(object sender, RoutedEventArgs e)
{
int rowIndex = 0;

DependencyObject dep = (DependencyObject)e.OriginalSource;
while (dep != null && !(dep is DataGridCell))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;
DataGridRow row = null;
if (dep is DataGridCell)
{
while (dep != null && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}

row = (DataGridRow)dep;
rowIndex = FindRowIndex(row);
}

while (dep != null && !(dep is DataGrid))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

DataGrid dg = (DataGrid)dep;

dg.CurrentCell = new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[0]);
dg.BeginEdit();

for (int column = 0; column <= dg.Columns.Count - 1; column++)
{
if (!(GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsReadOnly))
{
GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing = true;
}
}

var rows = GetDataGridRows(dg);

foreach (DataGridRow r in rows)
{
if (!(r.IsEditing))
{
r.IsEnabled = false;
}
}
}

private void SaveButton_Click(object sender, RoutedEventArgs e)
{
int rowIndex = 0;

DependencyObject dep = (DependencyObject)e.OriginalSource;
while (dep != null && !(dep is DataGridCell))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

DataGridRow row = null;

if (dep is DataGridCell)
{

while (dep != null && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}

row = (DataGridRow)dep;
rowIndex = FindRowIndex(row);

}

while (dep != null && !(dep is DataGrid))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

DataGrid dg = (DataGrid)dep;

dg.CommitEdit(DataGridEditingUnit.Row, true);

for (int column = 0; column <= dg.Columns.Count - 1; column++)
{
if (!(GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsReadOnly))
{
GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing = false;
}
}

var rows = GetDataGridRows(dg);

foreach (DataGridRow r in rows)
{
r.IsEnabled = true;
}
}

private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;

int rowIndex = 0;

DataGridRow row = null;

while (dep != null && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}

row = (DataGridRow)dep;
rowIndex = FindRowIndex(row);

while (dep != null && !(dep is DataGrid))
{
dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
return;

DataGrid dg = (DataGrid)dep;

var rows = GetDataGridRows(dg);

dg.CancelEdit(DataGridEditingUnit.Row);

for (int column = 0; column <= dg.Columns.Count - 1; column++)
{
if (!(GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsReadOnly))
{
GetDataGridCell(new DataGridCellInfo(dg.Items[rowIndex], dg.Columns[column])).IsEditing = false;
}
}

foreach (DataGridRow r in rows)
{
r.IsEnabled = true;
}
}

private void DataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
DataGrid dg = (DataGrid)sender;
foreach (DataGridRow row in GetDataGridRows(dg))
{
row.IsEnabled = true;
}
}

private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (dataGrid.SelectedItem != null)
{
dataGrid.ScrollIntoView(dataGrid.SelectedItem);
}
}

public DataGridCell GetDataGridCell(DataGridCellInfo cellInfo)
{
var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
if (cellContent != null)
return (DataGridCell)cellContent.Parent;

return null;
}

private int FindRowIndex(DataGridRow row)
{
DataGrid dataGrid = ItemsControl.ItemsControlFromItemContainer(row) as DataGrid;

int index = dataGrid.ItemContainerGenerator.IndexFromContainer(row);

return index;
}

public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
{
var itemsSource = grid.ItemsSource as IEnumerable;
if (null == itemsSource) yield return null;
foreach (var item in itemsSource)
{
var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
if (null != row) yield return row;
}
}
}

最后是 ViewModel 的代码:

public class ListViewModel : ViewModelBase
{
ERPLiteDBContext db = new ERPLiteDBContext();

public ListViewModel()
{
Groups = new ObservableCollection<Group>(db.Groups);
ParentGroups = new ObservableCollection<Group>(db.Groups);

EditCommand = new RelayCommand(Edit);
SaveCommand = new RelayCommand(Save);
DeleteCommand = new RelayCommand(Delete);
CancelCommand = new RelayCommand(Cancel);
DataGridRowEditEndingCommand = new RelayCommand(DataGridRowEditEnding);

SearchGroupName = "";
IsInEdit = false;
}

public RelayCommand EditCommand { get; set; }
public RelayCommand SaveCommand { get; set; }
public RelayCommand DeleteCommand { get; set; }
public RelayCommand CancelCommand { get; set; }
public RelayCommand DataGridRowEditEndingCommand { get; set; }

private string _searchGroupName;
public string SearchGroupName
{
get
{
return _searchGroupName;
}
set
{
if (value == null)
{
SearchGroupName = "";
}
else
{
_searchGroupName = value;
}

OnPropertyChanged("SearchGroupName");

SelectedGroup = db.Groups.AsEnumerable().OrderBy(x => x.GroupName).Where(x => x.GroupName.StartsWith(SearchGroupName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

if (SelectedGroup == null)
{
SelectedGroup = db.Groups.AsEnumerable().OrderBy(x => x.GroupName).Where(x => x.GroupName.Contains(SearchGroupName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
}

}
}

private ObservableCollection<Group> _groups;
public ObservableCollection<Group> Groups
{
get
{
return _groups;
}
set
{
_groups = value;
OnPropertyChanged("Groups");
}
}

private Group _selectedGroup;
public Group SelectedGroup
{
get
{
return _selectedGroup;
}
set
{
_selectedGroup = value;
OnPropertyChanged("SelectedGroup");

if (value != null)
{
ParentGroups = new ObservableCollection<Group>(db.Groups.Where(x => x.GroupID != value.GroupID));
ParentGroups.Add(new Group { GroupID = -1, GroupName = "Primary" });
}
}
}

private ObservableCollection<Group> _parentGroups;
public ObservableCollection<Group> ParentGroups
{
get
{
return _parentGroups;
}
set
{
_parentGroups = value;
OnPropertyChanged("ParentGroups");
}
}

private Group _selectedParentGroup;
public Group SelectedParentGroup
{
get
{
return _selectedParentGroup;
}
set
{
_selectedParentGroup = value;
OnPropertyChanged("SelectedParentGroup");
}
}

private bool _isInEdit;
public bool IsInEdit
{
get
{
return _isInEdit;
}
set
{
_isInEdit = value;
OnPropertyChanged("IsInEdit");
}
}

private void Edit(object obj)
{
IsInEdit = true;
}

private void Save(object obj)
{
IsInEdit = false;
SaveToDataBase();
}

private void Delete(object obj)
{

}

private void Cancel(object obj)
{
IsInEdit = false;
}

private void DataGridRowEditEnding(object obj)
{
IsInEdit = false;
}

public void SaveToDataBase()
{
Group currentGroup = db.Groups.Where(x => x.GroupID == SelectedGroup.GroupID).FirstOrDefault();
if (currentGroup != null)
{
currentGroup.GroupName = SelectedGroup.GroupName;
if (SelectedGroup.ParentID == -1)
{
currentGroup.ParentID = null;
}
else
{
currentGroup.ParentID = SelectedGroup.ParentID;
}

db.SaveChanges();
}
}
}

我不确定问题出在哪里,所以,我把几乎所有的代码都贴在这里。

我已经创建了一个示例项目,可以从下面的链接下载:

项目:

https://drive.google.com/file/d/0B5WyqSALui0bTTNsMm5ISHV3VEk/view?usp=sharing

数据库:

https://drive.google.com/file/d/0B5WyqSALui0bTXVJanp4TE9iSGs/view?usp=sharing

编辑 1:

原始问题(如图所示)已解决

为了解决这个问题,我删除了 CollectionViewSource 并将 ComboBox 直接绑定(bind)到 ViewModel 属性。现在我得到另一个错误:

enter image description here

当我看到 InnerException 时:

enter image description here

我在网上搜索了这个错误,但随处可见,如果我在外键列中插入 NULL 值,就会出现这个错误。但是我的列是可空的,我需要插入空值。

编辑2:

我已经解决了编辑 1 中提到的错误。

在名为 Primary 的表中添加了一条新记录作为第一条记录。并删除了所有与 Primary Group 相关的编码。将数据库中的 NULL 替换为主要组。

现在剩下的唯一问题是使用 CollectionViewSource 作为组合框的源来对数据进行排序,而不是将组合框直接绑定(bind)到 ViewModel 中的属性。有人能回答这个问题吗????

最佳答案

问题解决了。请参阅有问题的编辑 1 和编辑 2,了解一半的解决方案。

在 Edit 2 之后,我无法使用 CollectionViewSource 对 ComboBox 中的数据进行排序。因此,我在查询中使用了 OrderBy。现在 ComboBox 中的数据已按预期排序。现在,我的查询如下所示:

ParentGroups = new ObservableCollection<Group>(db.Groups.OrderBy(x => x.GroupName));

现在 DataGrid 按预期工作。

我已经发布了这个解决方案,因为我认为它可能会对将来的人有所帮助。

感谢大家有兴趣解决我的问题。

在这里您可以找到工作示例:

项目:https://drive.google.com/file/d/0B5WyqSALui0beC05VnpMY1hzV3c/view?usp=sharing

数据库:https://drive.google.com/file/d/0B5WyqSALui0bTXVJanp4TE9iSGs/view?usp=sharing

关于c# - DataGrid 的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27189704/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com