前提・実現したいこと
ReactiveProperty
を使ってWPFアプリケーションを作成しています.
UIの要素をReactivePropertyにBindingして,中身にそって表示内容を変えたいと考えています.
発生している問題・エラーメッセージ
UIの表示が書き換わってくれません.
デバッグして,実際にReactivePropertyの値が書き換わっているのは確認してあります.
該当のソースコード
Person.cs
C#
1using Prism.Mvvm; 2 3namespace ForTeratail.Models 4{ 5 public class Person : BindableBase 6 { 7 public int Id { get; set; } 8 9 string m_name; 10 public string Name 11 { 12 get { return m_name; } 13 set { SetProperty(ref m_name, value); } 14 } 15 16 public Person(int id) 17 { 18 Id = id; 19 } 20 } 21}
PersonList.cs
C#
1using Prism.Mvvm; 2using Reactive.Bindings; 3 4namespace ForTeratail.Models 5{ 6 public sealed class PersonList : BindableBase 7 { 8 static readonly PersonList m_instance = new PersonList(); 9 10 public static PersonList Instance 11 { 12 get { return m_instance; } 13 } 14 15 int count; 16 17 private PersonList() 18 { 19 count = 0; 20 PersonCollection = new ReactiveCollection<Person>(); 21 Add(); 22 } 23 24 ReactiveCollection<Person> m_collection; 25 public ReactiveCollection<Person> PersonCollection 26 { 27 get { return m_collection; } 28 set { SetProperty(ref m_collection, value); } 29 } 30 31 Person m_current; 32 public Person CurrentPerson 33 { 34 get { return m_current; } 35 set { SetProperty(ref m_current, value); } 36 } 37 38 public void Add() 39 { 40 Person p = new Person(count); 41 PersonCollection.Add(p); 42 CurrentPerson = PersonCollection[PersonCollection.Count - 1]; 43 count++; 44 } 45 } 46}
MainWindowViewModel.cs
C#
1using System.Reactive.Linq; 2using Prism.Mvvm; 3using Reactive.Bindings; 4using Reactive.Bindings.Extensions; 5using ForTeratail.Models; 6using System; 7 8namespace ForTeratail.ViewModels 9{ 10 public class MainWindowViewModel : BindableBase 11 { 12 private string _title = "Prism Application"; 13 public string Title 14 { 15 get { return _title; } 16 set { SetProperty(ref _title, value); } 17 } 18 19 public ReactiveCollection<Person> Collection { get; } 20 public ReactiveProperty<Person> CurrentPerson { get; } 21 22 public ReactiveCommand<string> NameRegisterCommand { get; } 23 public ReactiveCommand AddCommand { get; } 24 25 public MainWindowViewModel() 26 { 27 Collection = PersonList.Instance.PersonCollection; 28 CurrentPerson = PersonList.Instance.ToReactivePropertyAsSynchronized(x => x.CurrentPerson); 29 CurrentPerson.Subscribe(_ => PersonChanged(CurrentPerson.Value)); 30 31 NameRegisterCommand = new ReactiveCommand<string>().WithSubscribe(x => 32 { 33 CurrentPerson.Value.Name = x; 34 }); 35 36 AddCommand = new ReactiveCommand().WithSubscribe(PersonList.Instance.Add); 37 } 38 39 public ReactiveProperty<string> Introduction { get; private set; } 40 41 void PersonChanged(Person p) 42 { 43 Introduction = p.ObserveProperty(x => x.Name) 44 .Select(x => x != null ? "I am " + x : "").ToReactiveProperty(); 45 } 46 } 47}
MainWindow.xaml
Xaml
1<Window x:Class="ForTeratail.Views.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:prism="http://prismlibrary.com/" 5 prism:ViewModelLocator.AutoWireViewModel="True" 6 Title="{Binding Title}" Height="350" Width="525"> 7 <Grid> 8 <Grid.RowDefinitions> 9 <RowDefinition/> 10 <RowDefinition/> 11 <RowDefinition/> 12 </Grid.RowDefinitions> 13 <Grid.ColumnDefinitions> 14 <ColumnDefinition/> 15 <ColumnDefinition/> 16 </Grid.ColumnDefinitions> 17 <ComboBox Grid.Column="0" Margin="10 20" 18 ItemsSource="{Binding Collection}" 19 SelectedValue="{Binding CurrentPerson.Value}" 20 DisplayMemberPath="Id" /> 21 <Button Grid.Column="1" Content="新規追加" Command="{Binding AddCommand}" Margin="20" /> 22 23 <TextBox Grid.Row="1" Grid.Column="0" Margin="10" Height="30" FontSize="18" 24 TextAlignment="Center" VerticalContentAlignment="Center" 25 x:Name="NameBlock"/> 26 <Button Grid.Row="1" Grid.Column="1" Content="登録" Margin="20" 27 Command="{Binding NameRegisterCommand}" 28 CommandParameter="{Binding Text, ElementName=NameBlock}" /> 29 30 <Label Grid.Row="2" Grid.ColumnSpan="2" Content="{Binding Introduction.Value}" /> 31 </Grid> 32</Window>
挙動
初期起動時に,CurrentPerson
ではId = 0
のオブジェクトが指定されています.
そのときに,NameRegisterCommandでCurrentPersonのNameプロパティを書き換えると,きちんとIntroductionの値も変わってくれて,その値が描画されます.
しかし,新規追加をしてId = 1
のPersonオブジェクトに切り替わると,UIには以前のIntroductionが表示されたままになります.
デバッグをすると,Introducitonの中身はきちんと想定通りの値に変わっております.
なにが問題でしょうか?
補足情報(FW/ツールのバージョンなど)
Visual Studio 2017 Community
.NET Framework 4.6.1