2013-08-02 23 views
10

MVVMパターンを使用しており、DataGridのSelectedItemのXAMLでバインディングを作成しました。私はプログラムによってSelectedItemを設定しますが、そうした場合、DataGridは選択範囲にスクロールしません。 MVVMパターンを完全に破ることなくこれを達成できる方法はありますか?これは動作するはずhttp://www.codeproject.com/Tips/125583/ScrollIntoView-for-a-DataGrid-when-using-MVVMWPF DataGrid(MVVM)のScrollIntoView

+0

'Behavior'を実装しようとすると、どのようなエラーが発生しますか? – Gjeltema

+0

@Gjeltema '型または名前空間の名前 'ビヘイビア'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?) ' – Andy

+0

プロジェクトにSystem.Windows.Interactivity.dllへの参照がありますか? – Gjeltema

答えて

29

:私はブレンドSDKをインストールしたにも関わらず、

は、私は、次の解決策を見つけましたが、私は Behaviorクラスを実装しようとすると、私はエラーを取得します。あなたは DataGridに添付するこの添付プロパティを持っているということです。あなたがそれを添付するxamlでは、それをあなたの ViewModelのプロパティにバインドします。プログラムで SelectedItemに値を割り当てる場合は、このプロパティに値を設定します。このプロパティには、接続プロパティがバインドされています。

添付プロパティの種類をSelectedItemの種類に変更しましたが、以前とは異なる種類に設定している限り、正にその種類は関係ありません。このアタッチされたプロパティは、MVVMフレンドリーな方法でビューコントロール(この場合はDataGrid)上のコードを実行するための手段として使用されています。

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); 
      })); 
     } 
    } 
} 

をそしてここで、XAMLスニペットです:

だから、言ったこと、ここに添付プロパティのためのコードです

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

+1ありがとうございます。しかし、私は次のエラーが表示されます: 'System.Windows.Threading.Dispatcher 'に' InvokeAsync 'の定義がなく、' System.Windows.Threading.Dispatcher '型の最初の引数を受け入れる拡張メソッド' InvokeAsync 'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?) '。なぜどんなアイデア?私は 'MySelectionType'を変更しました – Andy

+0

@Andy謝罪、私はまだ.Net 4.5で働いています。 .Net 4.0を反映するように私の答えを更新します。 – Gjeltema

+0

ああ、こんにちは、それは大丈夫です!これは完全に今働いています - 1つ少ないDLL!私はあなたの答えをもう一度upvoteすることを願っています! – Andy

6

私はMVVMに新しいです。私はMVVMのアイデアを理解し、すべてを正しく実装しようとします。 私は上記と同様の問題があり、XAMLでは1行、コードは1行で終了しました。残りのコードはVM内にあります。 私はXAML

背後にあるコードで
<ListBox DockPanel.Dock="Top" 
    Name="Selection1List" 
    ItemsSource="{Binding SelectedList1ItemsSource}" 
    SelectedItem="{Binding SelectedList1Item}" 
    SelectedIndex="{Binding SelectedList1SelectedIndex}" 
    SelectionChanged="Selection1List_SelectionChanged"> 

そして、これで次のようでした:

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

と、これは正常に動作します。

私は、ウィンドウの背後にあるコードに1行のコードさえしたくない人もいることを知っています。しかし、私はこの1行は見通しだと思います。データやデータのロジックとは何の関係もありません。だから私はこれがMVVMの原則に違反していないと思っています。

コメントは大歓迎です。

関連する問題