2011-01-17 2 views
2

ObservableCollection에 WPF Datagrid의 ItemsSource 속성을 바인딩하고 있습니다. 데이터가 잘 잡히지 만 셀 (모든 셀)을 클릭하고 키보드를 사용하여 탐색 할 때 이상한 동작을 감지합니다.WPF DataGrid 화살표 (오른쪽/왼쪽) 키 탐색 예외

  1. 예상대로 탭 키가 작동합니다 (왼쪽에서 오른쪽으로 다음 줄 바꿈까지).
  2. 위쪽 키는 아무 작업도 수행하지 않습니다 (선택한 셀에 포커스가 유지됩니다).
  3. 아래쪽 키를 누르면 포커스가 열의 맨 위 셀로 이동합니다. 예를 들어 B 열의 10 행에 있고 "아래로"누르면 집중식 셀이 B 열의 0 행이됩니다.
  4. 왼쪽 또는 오른쪽 키를 누르면 ArgumentOutOfRangeException이 발생합니다. "지정된 인수가 유효한 값의 범위를 벗어났습니다. 매개 변수 이름 : 색인" InnerException은 없으며 Stack Trace는별로 도움이되지 않습니다.
  5. 셀을 두 번 클릭해도 편집 모드가 활성화되지 않습니다.
  6. 올바른 기능 (오른쪽/왼쪽 단추 작동, 두 번 클릭 트리거 편집 모드)이있는 눈금의 맨 아래에 어떤 이유로 "추가"행 (rowcount = (수집 횟수 +1))이 발생합니다. 이 여분의 행에 편집 모드를 입력하기 위해 더블 클릭 한 다음 위에있는 바운드 행을 클릭하면 여분의 행이 눈금에 추가됩니다.

나는 (XAML과 대조적으로) 바운드 ViewModel 클래스로 사고를 격리했다고 생각합니다. 예비 디버깅에서는 XAML을 최소한으로 줄였습니다 (스타일, 2 열, 바인딩 만 ItemsSource 임). 여전히 이상한 동작을 얻습니다. 의 InitializeComponent (에서 제외

<UserControl x:Name="FuelMileageView" x:Class="TRD.RaceStrategy.Views.FuelMileage" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:TRD.RaceStrategy" 
     xmlns:views="clr-namespace:TRD.RaceStrategy.Views" 
     xmlns:vm="clr-namespace:TRD.RaceStrategy.ViewModels;assembly=RaceStrategy.Support" 
     xmlns:converters="clr-namespace:TRD.RaceStrategy.Converters;assembly=RaceStrategy.Support" 
     xmlns:Behaviours="clr-namespace:TRD.RaceStrategy.Behaviours;assembly=RaceStrategy.Support" 
     mc:Ignorable="d" DataContext="{Binding Path=Properties[PrimaryVM].CarEventVM.FuelMileage.FuelMileageLaps, Source={x:Static local:App.Current}}" 
     d:DesignHeight="410" d:DesignWidth="485"> 

<DataGrid x:Name="dgFMLaps" ItemsSource="{Binding}" 
      AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Column 1" > 
     </DataGridTextColumn> 
     <DataGridTextColumn Header="Column 2" > 
     </DataGridTextColumn> 
    </DataGrid.Columns>    
</DataGrid> 
</UserControl> 

)의 유일한 원인으로 바운드 FuelMileageLaps 수집을 떠날 보이는 이야기 할 코드 숨김이없는 호출합니다.

public class FuelMileageLapViewModel : LapViewModel 
{ 
    public FuelMileageLapViewModel() { }  
} 

참고 : (?) ObservableCollectionEx 분명히 스레딩 문제를 차지하는 ObservableCollection에 클래스 I이 없었 내가 DataGrids를에 연결 차례로했습니다 다른 컬렉션이 클래스를 사용했습니다의 확장 키보드 탐색 문제.

public class ObservableCollectionEx<T> : ObservableCollection<T> 
{ 
    // Override the event so this class can access it 
    public override event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged; 

    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     // Be nice - use BlockReentrancy like MSDN said 
     using (BlockReentrancy()) 
     { 
      System.Collections.Specialized.NotifyCollectionChangedEventHandler eventHandler = CollectionChanged; 
      if (eventHandler == null) 
       return; 

      Delegate[] delegates = eventHandler.GetInvocationList(); 
      // Walk thru invocation list 
      foreach (System.Collections.Specialized.NotifyCollectionChangedEventHandler handler in delegates) 
      { 
       DispatcherObject dispatcherObject = handler.Target as DispatcherObject; 
       // If the subscriber is a DispatcherObject and different thread 
       if (dispatcherObject != null && dispatcherObject.CheckAccess() == false) 
       { 
        // Invoke handler in the target dispatcher's thread 
        dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, e); 
       } 
       else // Execute handler as is 
        handler(this, e); 
      } 
     } 
    } 
} 

이 시점에서 나는 디버깅을위한 다음 단계로서 내 기지에있다. 중단 점을 던지거나 try/catch 블록을 던질 분명한 곳이 없습니다. 나는 내 문제를 끈질 기게 괴롭혔고, 가치있는 것을 발견하지 못했다. 도와주세요! 나는이 오래된 질문 알고

public class FuelMileageViewModel : WorkspaceViewModel 
{ 
    /// <summary> 
    /// View model for the fuel mileage calculator 
    /// </summary> 
    /// <param name="car">Car on which to base all calculations</param> 
    public FuelMileageViewModel() 
    {} 

    /// <summary> 
    /// A separate collection of laps that store the extra fuel mileage data 
    /// </summary> 
    public ObservableCollectionEx<FuelMileageLapViewModel> FuelMileageLaps 
    { 
     get 
     { 
      if (_fuelMileageLaps == null) 
      { 
       _fuelMileageLaps = new ObservableCollectionEx<FuelMileageLapViewModel>(); 
      } 
      return _fuelMileageLaps; 
     } 
     set 
     { 
      _fuelMileageLaps = value; 
      OnPropertyChanged("FuelMileageLaps"); 
     } 
    } 
    private ObservableCollectionEx<FuelMileageLapViewModel> _fuelMileageLaps; 

    /// <summary> 
    /// Number of laps in the race 
    /// Affects: Laps_G, Laps_Y 
    /// </summary> 
    public int NumberOfLaps 
    { 
     get 
     { 
      return FuelMileageLaps.Count; 
     } 
     set 
     { 
      int count = FuelMileageLaps.Count; 

      if (value < 0) 
      { 
       throw new ArgumentException("Number of laps must be a positive integer"); 
      } 

      if (count != value) 
      { 
       if(count < value) 
       { 
        int diff = value - count; 
        for (int i = 0; i < diff; i++) 
        { 
         FuelMileageLapViewModel lapToAdd = new FuelMileageLapViewModel(); 

         FuelMileageLaps.Add(lapToAdd); 
        } 
       } 
       OnPropertyChanged("NumberOfLaps"); 
      } 
     } 
    } 
} 
+0

이 문제를 재현 할 수있는 소스 코드에 대한 링크를 게시 할 수 있습니까? 위의 코드를 컴파일 가능한 솔루션으로 가져 오는 데는 시간이 걸릴 수 있습니다. – grantnz

답변

0

하지만 최근 데이터 그리드와 아주 유사한 문제가되었다

여기 FuelMileageLaps가 초기화됩니다 FuelMileageViewModel 클래스입니다. 화살표 키 문제는 당신이 묘사 한 것과 똑같습니다. 그러나 TextBox를 편집 할 수있는 DataGridTemplateColumns를 사용했습니다 (그렇지 않은 경우 명시된대로 데이터를 편집 할 수 없음). 셀을 편집 한 다음 클릭하면 (특히 위 행을 클릭하면) DataGrid에서 중복 행을 생성합니다 (컬렉션의 수가 동일하게 유지 되더라도).

내 경우에는 ObservableCollection에있는 멤버가 DataGrid에 바인딩 된 클래스에 대해 Equals (object obj) 메서드에서 버그를 발견했습니다. 이것은 Equals에 대한 호출이 두 항목 간의 진정한 평등을 결정하는 것을 막았고, 어떻게 든 이것이 큰 문제를 야기했습니다.예를 들어, 행을 편집 한 후에 데이터 격자가 이미 목록에있는 동일한 행을 버그가있는 Equals 메서드를 통해 찾을 수없는 경우 다른 행을 생성합니다 (해당 행에 대해 아직 행이 없어야한다고 가정) .

어쨌든 LapViewModel에서 Equals 메서드를 확인하는 것이 좋습니다.

희망이 있습니다.