매우 복잡한 문제가 있습니다. 나는 모든 것을 검사하려고 노력했고이 문제에 대해 거의 6 시간 가까이 일했습니다. 그러나 나는이 문제를 해결하는데 성공하지 못했다. 그래서, 여기에 질문이 있습니다.예기치 않은 DataGrid 동작
문제 : 처음
때 프로그램로드까지 :
내가 어떤 행을 편집 버튼을 클릭
:
나는 것을 저장 행 :
내가 다른 부모 그룹을 갖는 다른 행에 편집 버튼을 클릭하면 :
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;
}
}
}
내가 여기에 거의 모든 코드를 게시,
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
나는 아래 링크에서 다운로드 할 수있는 샘플 프로젝트를 만들었습니다 10,403,210 편집 1
원래의 문제 (이미지에 도시 된 바와 같이) I는 CollectionViewSource 제거 문제를 해결하기
해결하고 뷰 모델 속성에 직접 콤보 바인딩된다. 지금은 또 다른 오류가 발생합니다 :내가 볼의 InnerException :이 오류에 대한 그물을 수색하지만 모든 곳에서 내가 볼 수
그 난에 NULL 값을 삽입하는 경우 외래 키 열 다음이 오류가 발생합니다. 하지만 내 열은 Nullable이며 null을 삽입해야합니다.
편집 2 : 내가 편집 1.
추가 차라고 테이블의 첫 번째 레코드로 새로운 기록에 언급 된 오류를 해결 한
. 그리고 Primary Group과 관련된 모든 코딩을 제거했습니다. 데이터베이스의 NULL을 기본 그룹으로 바꿨습니다.
이제 남은 유일한 문제는 콤보 상자를 ViewModel 내부의 속성에 직접 바인딩하는 대신 데이터를 정렬하기 위해 콤보 상자의 소스로 CollectionViewSource를 사용하는 것입니다. 아무도이 질문에 대답 할 수 있습니까 ????
프로젝트를 압축하여 보관 용에 업로드 할 수 있을까요? 디버깅을 원하는 사람들의 시간을 절약 할 수 있습니다. – kennyzx
[mcve] (http://stackoverflow.com/help/mcve)를 준비 할 수 있습니까? 디버깅보다 훨씬 좋습니다. 그러한 예를 준비하는 동안 모든 단계를 다시 거치게되며 문제가 여전히 지속되면 좋은 징조로 해결할 수 없습니다. 그러나 더 자주, 당신은 * 비정상적인 * 또는 * 비정상적인 * 것을 발견함으로써 그것을 해결할 것입니다. – Sinatr
@kennyzx Google 드라이브에 내 프로젝트와 데이터베이스를 업로드했습니다. 내 질문에 링크를 다운로드하여 업데이트했습니다. – Vishal