この質問が何度も聞かれるのを見て、自分のコードを何度も調べてきました。しかしSelectedItem
、オブジェクトを使用してバインドされたプロパティに割り当てると、ディスプレイの選択されたアイテムが更新されません。はListBox
、割り当てたオブジェクトがそのアイテムのメンバーではないと考えているようです。
public class MainViewModel : ViewModelBase
{
//...
public SortedObservableCollection<TubeViewModel> Items { get; private set; }
public TubeViewModel SelectedTube { //get, set, propertychanged, etc. }
}
<ListBox x:Name="TubeList"
Margin="10"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource TubeTemplate}"
SelectedItem="{Binding SelectedTube, Mode=TwoWay}"
SelectionMode="Single"
VirtualizingStackPanel.IsVirtualizing="False">
</ListBox>
これは、私が設定しようとしている場所の 1 つからの impl ですSelectedTube
- 間違いなくメイン スレッドで発生します。
var match =
from t in Items
where t.Model.DataFileName == filename
select t;
if (match.Any())
SelectedTube = match.First();
手動でクリックしない限り強調表示されないことに気付きましたSelectedTube
が、無視していました。しかし、選択したアイテムをScrollIntoViewCenteredしたかったので、変更DependencyProperty
を監視するためにビューにa を追加しましたSelectedItem
。ハンドラーは最初は次のように見えました。
private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
if (TubeList.SelectedItem == null)
return;
TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);
}
SelectedItem
しかし、バインディングを介して設定すると機能しませんでした。画面上にない場合にのみスクロールしたいと判断した後、コードを次のように変更しました。
private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
if (TubeList.SelectedItem == null)
return;
var container = TubeList.ItemContainerGenerator.ContainerFromItem(TubeList.SelectedItem) as FrameworkElement;
if(!container.IsVisible)
TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);
}
が外部で設定されている場合SelectedItem
、コンテナは null です。毎回。ItemsSource
null をチェックするコードを追加してから、一致するファイル名を探して繰り返し処理し、更新してリストボックス内のオブジェクトが間違いないSelectedItem
ことを確認しました。SelectedItem
運がない。
アイテムが画面上にある場合、それはまだ強調表示されません。ある種の等価関数を実装する必要がありますか? 私はこれについて、人が考えているよりも多くの時間を無駄にしました。
ありがとう。