2011-07-26 15 views
8

Bunu araştırdım ve şaşırıyorum: Bir WPF DataGrid'im var ve bir MVVM modeli kullanıyor. Belirli koşullar altında DataGrid'de bir satırı değiştirme yeteneğini önlemek istiyorum. Bunu araştırdım ve here gibi teknikler denedim. Pratikte, bu çalışma, bununla birlikte, istenmeyen bir 'titreşim' (bir an için tıklanan satırı seçer, sonra bir önceki seçime geri döner) yapar, bu yakın bir çözümdür, daha zarif bir yolun olmasını isterdim. İlk başta satır değişimini engellemek gibi.datagrid'de satır değişikliğini önleme

Bir SelectionChanging veya BeforeSelectionChanged olmadığına şaşırdım, böylece etkinliği iptal etmek için iptal edebilirdim; ve benim görüş modelimde dizin değişikliğini zorla önleme, herhangi bir fark yaratmıyor gibi görünüyor.

Bunu nasıl yapabilirim?

Teşekkür ederiz.

cevap

5

previewkeydown ve previewmousedown olaylarını kabul ederseniz ve yalnızca belirli bir koşul altında e.Handled=true'u arayarak ne olur?

Düzenleme: MVVM stilini karşılamak için: Eğer sizin durum bağlanabilen bir BehaviorDependencyProperty bir ile oluşturabilirsiniz. Bu davranışta, olayları ve belki de diğer bazı şeyleri kullanabilirsiniz, kullanıcı bir veriyi veya başlığa tıklar ...

+0

Eski öneri mükemmel çalıştı (ikincisi çok ilginç bir öneri olsa da ve bunu denemeyi de düşündüm) - Teşekkür ederim. – Mani5556

2

DispatcherPriority ContextIdle olarak ayarlanmış. Bu, SelectedItem öğesinin iki kez ayarlandığından (ve iki kez oluşturulduğundan) dolayı titremenizi sağlar. Sadece önceliği Normal olarak ayarlayın ve artık yanıp sönmüyor olacaksınız.

+0

Bu bana yardımcı oldu, teşekkürler. –

0

PreviewMouseDown yöntemi here için bazı örnekler vardır.

Genel anlaşma, DataGrid.SelectedItem öğesini datagrid'in SelectionChanged işleyicisindeki orijinal değerine geri döndürmenin beklendiği gibi çalışmadığıdır; Çalışıyor gibi görünen tüm kod örnekleri, Dağıtımcının daha sonra zamanlamasını yapmasını isteyerek geri çekmeyi erteler.

Veri bölümünüzde bir CellStyle var mı? Benim için çalıştı aşağıdaki:

xaml:

<DataGrid.CellStyle> 
    <Style TargetType="{x:Type DataGridCell}"> 
     <Style.Triggers> 
      <Trigger Property="IsSelected" Value="True"> 
       <Setter Property="Background" Value="DarkSlateBlue"/> 
       <Setter Property="Foreground" Value="White"/> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</DataGrid.CellStyle> 

codebehind:

private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if (e.AddedItems.Count > 0) 
    { 
     object x = e.AddedItems[0]; 
     if (x is MyObjectType && x != myViewModel.CurrentItem && 
      myViewModel.ShouldNotDeselectCurrentItem()) 
     { 
      // this will actually revert the SelectedItem correctly, but it won't highlight the correct (old) row. 
      this.MyDataGrid.SelectedItem = null; 
      this.MyDataGrid.SelectedItem = myViewModel.CurrentItem; 
     } 
    } 
} 

noktası SelectedCellsChanged olay SelectionChanged olaydan sonra ateş olmasıydı - ve özellikle de bu ayarı SelectedItem, salt okunur bir özellik olan SelectedCells'i doğru şekilde güncelleştirmez, bu nedenle daha fazla codebehind:

private void MyDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e) 
{ 
    List<DataGridCellInfo> selectedCells = MyDataGrid.SelectedCells.ToList(); 

    List<MyObjectType> wrongObjects = selectedCells.Select(cellInfo => cellInfo.Item as MyObjectType) 
     .Where (myObject => myObject != myViewModel.CurrentItem).Distinct().ToList(); 
    if (wrongObjects.Count > 0) 
    { 
     MyDataGrid.UnselectAllCells(); 
     MyDataGrid.SelectedItem = null; 
     MyDataGrid.SelectedItem = myViewModel.CurrentItem; 
    } 
} 

Açıktır ki, işleyicilerin veri şebekesindeki ilgili olaylara bağlanması gerekir.

Bu, beklenen gibi çalıştı, istenirse seçim değişikliğini düzgün bir şekilde iptal etti ve bir titreme oluşturmadı.

İlgili konular