0

添付プロパティでBringIntoViewを使用して、リストボックスのスクロールを同期しようとしています。

私の試みはうまくいきません。コードを実行すると、選択したアイテムがリストボックス間で同期されますが、他のリストボックスに表示されていないアイテムを選択すると、自動的にスクロールしません。

IsShownプロパティとItemTextプロパティを持つ単純なViewModelがあります。

    <Window.Resources>
    <Style TargetType="ListBoxItem">
        <Setter Property="IsSelected" Value="{Binding IsShown, Mode=TwoWay}"/>
        <Setter Property="local:CustomProperties.BringIntoView" Value="{Binding IsShown}"/>
    </Style>
    <DataTemplate x:Key="DataTemplate1">
        <TextBlock Name="_txt" Text="{Binding ItemText}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="255*"/>
        <ColumnDefinition Width="262*"/>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding ItemList}" ItemTemplate="{StaticResource DataTemplate1}" />  
    <ListBox Grid.Column="1" ItemsSource="{Binding ItemList}" ItemTemplate="{StaticResource DataTemplate1}" >
    </ListBox>                
</Grid>

これが私の依存関係のプロパティです

public static class CustomProperties
{
    public static readonly DependencyProperty BringIntoViewProperty =
      DependencyProperty.RegisterAttached( "BringIntoView",
      typeof( bool ),
      typeof( CustomProperties ),
      new PropertyMetadata( OnBringIntoViewChanged ) );

    public static void SetBringIntoView ( DependencyObject o, bool value )
    {
        o.SetValue( BringIntoViewProperty, value );
    }

    public static bool GetBringIntoView ( DependencyObject o )
    {

        return ( bool )o.GetValue( BringIntoViewProperty );
    }

    private static void OnBringIntoViewChanged ( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
        if ( ( bool )e.NewValue )
        {
           if ( d is FrameworkElement )
                ( ( FrameworkElement )d ).BringIntoView();
        }
    }
}
4

1 に答える 1

0

別のアプローチはどうですか?

選択したアイテムを常に表示する必要があります。ViewModelでListCollectionViewを使用する場合は、MoveCurrentTo()およびその他の関数を呼び出して選択を変更できます。ListBoxはこのListCollectionViewにバインドされ、デフォルトでは、IsSynchronizedWithCurrentItemプロパティを使用して選択されたアイテムを同期します。

このようにして、ViewModelは現在のアイテムを追跡し、ListBoxはそれにバインドします。

ここで、リストボックスの動作にスクロールを含めて、選択したアイテムを表示したままにする場合は、次のコードをビューの分離コードに追加します。

private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    listBox.ScrollIntoView(listBox.SelectedItem);
}

ViewModelはおそらくこの詳細を知る必要はありません。自動スクロールは、ビューの動作の一部にすぎません。

すべてがViewModelにある必要があると想定するのはおそらく間違っています。たとえば、テキストボックス内のキャレットの位置は気にしません。これは、ビュー固有のものとして適格だと思います。

于 2012-09-14T20:47:32.433 に答える