none
WPF リストボックスのバインディングソースが更新されたら常に最終行を表示する RRS feed

  • 質問

  • お世話になります。

    表題の件、下記WEBの記事を参考に実装を行いました(環境はVBです)

    http://kenzauros.com/blog/follow-last-item-of-wpf-listbox/

    ですがソフト起動時にオブジェクトがからのため実行できないとのエラーメッセージが

    表示されます。VBへのソースのコンバート内容がだめなのかと、C#でも試しましたが

    同様の結果でした。

    お詳しい方お見えでしたらご教授願えませんでしょうか?

    2017年10月9日 21:34

回答

  • まず、webに出回っているWPFのコードのほとんどは、MVVMパターンで作成していることを前提にしていることをご承知ください。

    さて、listBox2のItemsSourceは、{Binding Items, 以下略}と定義されています。これは、「DataContextに設定されているオブジェクトの、Itemsという名前のプロパティをソースとして扱う」という意味になります。

    しかし、800ZOUさんはDataContextにObservableCollection<T>オブジェクトそのものを設定されています。ObservableCollection<T>はItemsプロパティを持っていないので、当然ながらItemsSourceはnullとなっていまいます。

    単純には、ItemsSource="{Binding Mode=以下略}"のように、パスを指定しないことで「DataContextに設定されているオブジェクトそのものをソースとして扱う」ことを意味させるなどといった解決策が考え付きます。

    あるいは、バインディングを使用しないコーディングスタイルで進めているのなら、{Binding}を使用せず、直接ItemsSourceプロパティにObservableCollection<T>を代入してしまってもいいでしょう。

    もっとも、冒頭で述べた通り、WPFのサンプルはおおよそMVVMパターンを前提に記述されていますので、まずはMVVMパターンを学んだほうが良いようには思います。

    2017年10月10日 1:10

すべての返信

  • こんにちは。

    ListBox.ItemsSourceにバインドしているプロパティの定義方法と生成タイミングはどうなってますか。
    サンプルが動くか確認してませんが、URLではViewModel側のサンプルまでは含まれていませんので、
    まず原因としてそちらを疑ってみてはどうでしょうか。

    2017年10月9日 22:20
    モデレータ
  • 技術的にどう解決して良いかというよりは、思った通りに動いてない、つまりデバッグの問題であるように思います。
    オブジェクトが空というのではあれば、原因はそこなので、空になっている原因を調査してみて下さい。
    最終行にスクロールする機能を実装する前に、ちゃんと表示されますか?

    もし、それでもわからない場合は、試されている最低限のコードをここに提示されると良いと思います。言葉で説明するよりもコードの方が的確に伝わることも多いです。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    2017年10月10日 0:23
    モデレータ
  • お世話になります。

    Viewmodel側のコードは下記となります。 

    <ListBox  x:Name="listBox2"  Grid.Row="4" ItemsSource="{Binding Items, Mode=OneWay, UpdateSourceTrigger =PropertyChanged, NotifyOnTargetUpdated=True}" TargetUpdated="ListBox_TargetUpdated"/>

    Web上の記事とほとんと変わらないかと思います。

    ソースコード記載部は下記となります。

     ①リストボックスの更新用のバインディングデータを下記で定義↓

      ObservableCollection<string> list = new ObservableCollection<string>();

    ②UIとのバインディング?を実施  

    listBox2.DataContext = this.list;

    ③イベントの登録。ソフト起動時に下記関数が実行され「オブジェクト参照がオブジェクトインスタンスに、、」とのエラーが

    発生します。listBox2.ItemsSourceの中身を見るとNULLになっております。

     private void ListBox_TargetUpdated(object sender, DataTransferEventArgs e)
            {
                (listBox2.ItemsSource as INotifyCollectionChanged).CollectionChanged += new NotifyCollectionChangedEventHandler(listBox_CollectionChanged);
         
            }
            void listBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                this.listBox2.ScrollIntoView(this.listBox2.Items[this.listBox2.Items.Count - 1]);
            }

    2017年10月10日 0:48
  • お世話になります。

    Viewmodel側のコードは下記となります。 

    表示もされていないので初期化時にエラーになっていることはわかります。

    <ListBox  x:Name="listBox2"  Grid.Row="4" ItemsSource="{Binding Items, Mode=OneWay, UpdateSourceTrigger =PropertyChanged, NotifyOnTargetUpdated=True}" TargetUpdated="ListBox_TargetUpdated"/>

    Web上の記事とほとんと変わらないかと思います。

    ListBox_TargetUpdatedがソフトの起動時呼ばれるようですが、その際にListBox2.Itemsourceの中身がNULLに

    なっているためにエラーが起きているようです。

    ソースコード記載部は下記となります。

     ①リストボックスの更新用のバインディングデータを下記で定義↓

      ObservableCollection<string> list = new ObservableCollection<string>();

    ②UIとのバインディング?を実施  

    listBox2.DataContext = this.list;

    ③イベントの登録。ソフト起動時に下記関数が実行され「オブジェクト参照がオブジェクトインスタンスに、、」とのエラーが

    発生します。listBox2.ItemsSourceの中身を見るとNULLになっております。

     private void ListBox_TargetUpdated(object sender, DataTransferEventArgs e)
            {
                (listBox2.ItemsSource as INotifyCollectionChanged).CollectionChanged += new NotifyCollectionChangedEventHandler(listBox_CollectionChanged);
         
            }
            void listBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                this.listBox2.ScrollIntoView(this.listBox2.Items[this.listBox2.Items.Count - 1]);
            }

    2017年10月10日 0:55
  • まず、webに出回っているWPFのコードのほとんどは、MVVMパターンで作成していることを前提にしていることをご承知ください。

    さて、listBox2のItemsSourceは、{Binding Items, 以下略}と定義されています。これは、「DataContextに設定されているオブジェクトの、Itemsという名前のプロパティをソースとして扱う」という意味になります。

    しかし、800ZOUさんはDataContextにObservableCollection<T>オブジェクトそのものを設定されています。ObservableCollection<T>はItemsプロパティを持っていないので、当然ながらItemsSourceはnullとなっていまいます。

    単純には、ItemsSource="{Binding Mode=以下略}"のように、パスを指定しないことで「DataContextに設定されているオブジェクトそのものをソースとして扱う」ことを意味させるなどといった解決策が考え付きます。

    あるいは、バインディングを使用しないコーディングスタイルで進めているのなら、{Binding}を使用せず、直接ItemsSourceプロパティにObservableCollection<T>を代入してしまってもいいでしょう。

    もっとも、冒頭で述べた通り、WPFのサンプルはおおよそMVVMパターンを前提に記述されていますので、まずはMVVMパターンを学んだほうが良いようには思います。

    2017年10月10日 1:10
  • 詳しいご説明を記載頂き誠にありがとうございました。

    解決することができましたのでお礼を申し上げます。

    MVVMをこれから少しづつ勉強していこうと思います。


    2017年10月12日 5:31