2013-08-02 33 views
10

MVVM desenini kullanıyorum ve bir DataGrid'in SelectedItem için bir XAML bağlaması oluşturdum. SelectedItem'i programlı olarak ayarlıyorum, ancak bunu yaptığımda DataGrid seçimi kaydırmıyor. MVVM modelini tamamen kırmadan bunu başarabileceğim bir yol var mı? Bu çalışması gerekir http://www.codeproject.com/Tips/125583/ScrollIntoView-for-a-DataGrid-when-using-MVVMWPF DataGrid (MVVM) için ScrollIntoView (MVVM)

+0

"Davranışı" uygulamaya çalışırken hangi hatayı alıyorsunuz? – Gjeltema

+0

@Gjeltema 'Tür veya ad alanı adı 'Davranış' bulunamadı (kullanma yönergesi veya montaj referansı eksik misiniz?)' – Andy

+0

Projenizde System.Windows.Interactivity.dll dosyasına bir başvuru var mı? – Gjeltema

cevap

29

: Ben Blend SDK yükledim rağmen

aşağıdaki çözüm bulduk ama Behavior sınıfı uygulamak çalıştığımda bir hata alıyorum. Fikrin, DataGrid'a ekleyeceğiniz ekli mülkünüz var. Taktığınız xaml'de, onu ViewModel'unuzdaki bir özelliğe bağlarsınız. Program aracılığıyla, SelectedItem'a bir değer atamak istediğinizde, ekli özelliğin bağlı olduğu bu özelliğe de bir değer ayarlarsınız.

Bağlı özellik türünü, SelectedItem türünde olduğu gibi yaptım, ancak dürüst olmak gerekirse, daha önce olduğundan daha farklı bir şeye ayarladığınız kadar uzun bir şey değil. Bu ekli özellik, sadece MVVM dostu bir şekilde görüntü denetiminde (bu durumda, DataGrid) bazı kodları yürütmek için bir araç olarak kullanılıyor.

namespace MyAttachedProperties 
{ 
    public class SelectingItemAttachedProperty 
    { 
     public static readonly DependencyProperty SelectingItemProperty = DependencyProperty.RegisterAttached(
      "SelectingItem", 
      typeof(MySelectionType), 
      typeof(SelectingItemAttachedProperty), 
      new PropertyMetadata(default(MySelectionType), OnSelectingItemChanged)); 

     public static MySelectionType GetSelectingItem(DependencyObject target) 
     { 
      return (MySelectionType)target.GetValue(SelectingItemProperty); 
     } 

     public static void SetSelectingItem(DependencyObject target, MySelectionType value) 
     { 
      target.SetValue(SelectingItemProperty, value); 
     } 

     static void OnSelectingItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      var grid = sender as DataGrid; 
      if (grid == null || grid.SelectedItem == null) 
       return; 

      // Works with .Net 4.5 
      grid.Dispatcher.InvokeAsync(() => 
      { 
       grid.UpdateLayout(); 
       grid.ScrollIntoView(grid.SelectedItem, null); 
      }); 

      // Works with .Net 4.0 
      grid.Dispatcher.BeginInvoke((Action)(() => 
      { 
       grid.UpdateLayout(); 
       grid.ScrollIntoView(grid.SelectedItem, null); 
      })); 
     } 
    } 
} 

Ve burada xaml pasajı var:

Yani, söz konusu, burada ekli özellik için kod

<Window ... 
     xmlns:attachedProperties="clr-namespace:MyAttachedProperties"> 
    ... 
     <DataGrid 
      attachedProperties:SelectingItemAttachedProperty.SelectingItem="{Binding MyViewModel.SelectingItem}"> 
      ... 
     </DataGrid> 
    </Grid> 
+0

+1 Cevabınız için çok teşekkür ederim. Ancak aşağıdaki hatayı alıyorum: 'System.Windows.Threading.Dispatcher '' InvokeAsync 'için bir tanım içermiyor ve' System.Windows.Threading.Dispatcher 'türünde bir ilk argümanı kabul eden' InvokeAsync 'uzantısı yok. (kullanma yönergesi veya montaj referansı eksik misiniz?) '. Herhangi bir fikir neden? 'MySelectionType' – Andy

+0

@Andy Özür dilerim, değiştirdim hala .Net 4.5 çalışıyorum. Cevabımı, .NET 4.0'ı yansıtacak şekilde güncelleyeceğim. – Gjeltema

+0

oh tamam haha, sorun değil! Şimdi mükemmel çalışıyor - bir daha az DLL! Tekrar cevap vermeyi dilemeyi dilerdim! – Andy

6

Ben MVVM için yeni. MVVM fikrini anlıyorum ve her şeyi doğru bir şekilde uygulamaya çalışıyorum. Yukarıdaki ile benzer bir sorun yaşadım ve XAML'de 1 satır ve arkada 1 satır kod yazdım. Kodun geri kalanı VM'de.

private void Selection1List_SelectionChanged(object sender, SelectionChangedEventArgs e) { 
    Selection1List.ScrollIntoView(Selection1List.SelectedItem); 
} 

ve düzgün çalıştığı: Ben

<ListBox DockPanel.Dock="Top" 
    Name="Selection1List" 
    ItemsSource="{Binding SelectedList1ItemsSource}" 
    SelectedItem="{Binding SelectedList1Item}" 
    SelectedIndex="{Binding SelectedList1SelectedIndex}" 
    SelectionChanged="Selection1List_SelectionChanged"> 

Ve bu kodda XAML

aşağıdaki yaptı.

Bazı kişilerin pencerenin arkasındaki kodda bir satır kod bile istemediklerini biliyorum. Ama bence bu 1 çizgi sadece görüş için. Verilerle veya verilerin mantığıyla ilgisi yoktur. Bu yüzden MVVM ilkesinin ihlal edilmediğini düşünürdüm - ve uygulanması çok daha kolay.

Herhangi bir yorum kabul edilir.