リスト ボックスを含む XAML ビューがあります。
<control:ListBoxScroll ItemSource="{Binding Path=FooCollection}"
SelectedItem="{Binding SelectedFoo, Mode=TwoWay}"
ScrollSelectedItem="{Binding SelectedFoo}">
<!-- data templates, etc. -->
</control:ListBoxScroll>
選択された項目は、ビュー内のプロパティにバインドされます。ユーザーがリスト ボックス内の項目を選択すると、ビュー モデルの SelectedFoo プロパティが更新されます。ビュー モデルで SelectedFoo プロパティを設定すると、リスト ボックス内の正しい項目が選択されます。
問題は、コードに設定されている SelectedFoo が現在表示されていない場合、ScrollIntoView
リスト ボックスをさらに呼び出す必要があることです。ListBox はビュー内にあり、ロジックはビュー モデル内にあるため、これを実行する便利な方法が見つかりませんでした。そこで、ListBoxScroll を拡張しました。
class ListBoxScroll : ListBox
{
public static readonly DependencyProperty ScrollSelectedItemProperty = DependencyProperty.Register(
"ScrollSelectedItem",
typeof(object),
typeof(ListBoxScroll),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(onScrollSelectedChanged)));
public object ScrollSelectedItem
{
get { return (object)GetValue(ScrollSelectedItemProperty); }
set { SetValue(ScrollSelectedItemProperty, value); }
}
private static void onScrollSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var listbox = d as ListBoxScroll;
listbox.ScrollIntoView(e.NewValue);
}
}
ScrollSelectedItem
基本的には、ビュー モデルのプロパティにバインドする新しい依存関係プロパティを公開しますSelectedFoo
。次に、依存プロパティのプロパティ変更コールバックにフックし、新しく選択された項目をスクロールして表示します。
ビュー モデルによってサポートされている XAML ビュー上のユーザー コントロールの関数を呼び出すより簡単な方法を知っている人はいますか? 少し回りくどいですが、次のようになります。
- 従属プロパティを作成する
- プロパティ変更コールバックにコールバックを追加する
- 静的コールバック内で関数呼び出しを処理する
ロジックをメソッド内に直接配置できればよいのですScrollSelectedItem { set {
が、依存関係フレームワークがこっそりと存在し、実際に呼び出さなくても動作してしまうようです。
ベストアンサー1
Behavior の使用を試しましたか... これは ScrollInViewBehavior です。これを ListView と DataGrid に使用しました... ListBox でも機能するはずです...
System.Windows.Interactivity
使用するには参照を追加する必要がありますBehavior<T> class
行動
public class ScrollIntoViewForListBox : Behavior<ListBox>
{
/// <summary>
/// When Beahvior is attached
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
}
/// <summary>
/// On Selection Changed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AssociatedObject_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
if (sender is ListBox)
{
ListBox listBox = (sender as ListBox);
if (listBox .SelectedItem != null)
{
listBox.Dispatcher.BeginInvoke(
(Action) (() =>
{
listBox.UpdateLayout();
if (listBox.SelectedItem !=
null)
listBox.ScrollIntoView(
listBox.SelectedItem);
}));
}
}
}
/// <summary>
/// When behavior is detached
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.SelectionChanged -=
AssociatedObject_SelectionChanged;
}
}
使用法
エイリアスを追加XAML
するxmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
あなたのControl
<ListBox ItemsSource="{Binding Path=MyList}"
SelectedItem="{Binding Path=MyItem,
Mode=TwoWay}"
SelectionMode="Single">
<i:Interaction.Behaviors>
<Behaviors:ScrollIntoViewForListBox />
</i:Interaction.Behaviors>
</ListBox>
ViewModel
これで、リストに「MyItem」プロパティが設定されている場合は、変更が反映されるときにリストがスクロールされるようになります。