私は MVVM パターンを使用しており、XAML で DataGrid の SelectedItem のバインディングを作成しました。SelectedItem をプログラムで設定しましたが、そうすると DataGrid が選択項目までスクロールしません。MVVM パターンを完全に壊すことなくこれを実現する方法はありますか?
Behavior
次の解決策を見つけましたが、 Blend SDK をインストールしたにもかかわらず、クラスを実装しようとするとエラーが発生します。http://www.codeproject.com/Tips/125583/ScrollIntoView-for-a-DataGrid-when-using-MVVM
ベストアンサー1
これは機能するはずです。アイデアとしては、 に添付する添付プロパティを用意することですDataGrid
。添付する xaml で、 のプロパティにバインドしますViewModel
。 プログラムで に値を割り当てる場合はSelectedItem
、添付プロパティがバインドされているこのプロパティにも値を設定します。
添付プロパティの型を任意の型にしましたがSelectedItem
、以前の型とは異なる型に設定する限り、型が何であっても問題ありません。この添付プロパティは、DataGrid
MVVM に適した方法でビュー コントロール (この場合は ) 上でコードを実行するための手段としてのみ使用されます。
つまり、添付プロパティのコードは次のとおりです。
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>