質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

4551閲覧

ReactivePropertyの値の変更をViewに反映したい

tohooky

総合スコア6

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2020/04/01 07:44

前提・実現したいこと

WPF(C#+XAML)でReactiveプログラミングの学習をしています。
Viewのボタンを押下するとModelの値が変更されてViewに表示されるようにしたいです。

イメージ

発生している問題・エラーメッセージ

「若返る」ボタンを押してもViewの表示が変わりません。
Modelの値が変更されるのは確認できましたので、ViewModelかViewに問題があると推測しています。
ReactivePropertyの使い方をよく理解できていないのだと思います。

該当のソースコード

Person.cs

C#

1 public class Person : BindableBase 2 { 3 public int Id { get; set; } 4 public string Name { get; set; } 5 public int Age { get; set; } 6 7 public Person() 8 { 9 Id = 1; 10 Name = "ひろし"; 11 Age = 55; 12 } 13 14 public void Younger() 15 { 16 Age--; 17 } 18 19 public void Elder() 20 { 21 Age++; 22 } 23 }

MainWindowViewModel.cs

C#

1public class MainWindowViewModel : BindableBase 2 { 3 PersonViewModel personViewModel; 4 public PersonViewModel PersonViewModel 5 { 6 get { return personViewModel; } 7 set { SetProperty(ref personViewModel, value); } 8 } 9 10 public Person Person { get; set; } 11 12 public MainWindowViewModel() 13 { 14 Person = new Person(); 15 //PersonViewModelにPersonを渡しています 16 PersonViewModel = new PersonViewModel(Person); 17 } 18 }

PersonViewModel.cs

C#

1 public class PersonViewModel : BindableBase 2 { 3 public ReactiveProperty<int> Id { get; private set; } 4 public ReactiveProperty<string> Name { get; private set; } 5 public ReactiveProperty<int> Age { get; private set; } 6 7 Person Person; 8 9 public ReactiveCommand YoungerCommand { get; } 10 public ReactiveCommand ElderCommand { get; } 11 12 public PersonViewModel(Person person) 13 { 14 Person = person; 15 this.Id = Person.ObserveProperty(x => x.Id).ToReactiveProperty(); 16 this.Name = Person.ToReactivePropertyAsSynchronized(x => x.Name); 17 this.Age = Person.ToReactivePropertyAsSynchronized(x => x.Age); 18 19 YoungerCommand = new ReactiveCommand().WithSubscribe(Person.Younger); 20 ElderCommand = new ReactiveCommand().WithSubscribe(Person.Elder); 21 } 22 }

PersonView.xaml

xaml

1<Page x:Class="ReactivePractice.Views.PersonView" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 mc:Ignorable="d" 7 d:DesignHeight="450" d:DesignWidth="800" 8 Title="MainView"> 9 <Grid> 10 <Grid> 11 <Grid.RowDefinitions> 12 <RowDefinition Height="auto"/> 13 <RowDefinition Height="auto"/> 14 <RowDefinition Height="auto"/> 15 <RowDefinition Height="auto"/> 16 <RowDefinition Height="auto"/> 17 <RowDefinition Height="auto"/> 18 <RowDefinition Height="auto"/> 19 <RowDefinition Height="auto"/> 20 <RowDefinition Height="auto"/> 21 </Grid.RowDefinitions> 22 23 <TextBlock Grid.Row="0" Text="Id"/> 24 <TextBox Grid.Row="1" 25 Text="{Binding Id.Value, Mode=TwoWay, 26 UpdateSourceTrigger=PropertyChanged}"/> 27 28 <TextBlock Grid.Row="2" Text="Name"/> 29 <TextBox Grid.Row="3" Text="{Binding Name.Value, Mode=TwoWay, 30 UpdateSourceTrigger=PropertyChanged}"/> 31 32 33 <TextBlock Grid.Row="4" Text="Age"/> 34 <TextBox Grid.Row="5" Text="{Binding Age.Value, Mode=TwoWay, 35 UpdateSourceTrigger=PropertyChanged}"/> 36 37 <Button Grid.Row="6" Command="{Binding YoungerCommand}"> 38 <TextBlock Text="若返る"/> 39 </Button> 40 <Button Grid.Row="7" Command="{Binding ElderCommand}"> 41 <TextBlock Text="老いる"/> 42 </Button> 43 </Grid> 44 </Grid> 45</Page> 46

質問

どのような記述をすればModelの値の変更がViewに反映されるのか、教えていただければ幸いです。

補足情報(FW/ツールのバージョンなど)

Visual Studio 2019 Professional
.Net framework 4.6.1

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Younger()を実行したときにAgeが変わるのは、作った人にしかわからないのでどうにかして知らせる必要があります。

INotifyPropertyChangedがそれです。
ToReactivePropertyAsSynchronizedINotifyPropertyChangedの変更通知を購読し、反映する仕組みですがPerson側で通知をしていません。
通知をしてください(Age2)

ReactivePropertySlimを使ってもよいでしょう(Age3)

Age { get; set; }を維持するならViewModel側で変えることになりますが、筋はよくなさそうです(Age1)

xml

1<Window 2 x:Class="Questions250717.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="800" 6 Height="450"> 7 <StackPanel> 8 <HeaderedContentControl Header="Age1"> 9 <TextBox Text="{Binding Age1.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 10 </HeaderedContentControl> 11 <HeaderedContentControl Header="Age2"> 12 <TextBox Text="{Binding Age2.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 13 </HeaderedContentControl> 14 <HeaderedContentControl Header="Age3"> 15 <TextBox Text="{Binding Age3.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 16 </HeaderedContentControl> 17 <Button Command="{Binding YoungerCommand}"> 18 <TextBlock Text="若返る" /> 19 </Button> 20 <Button Command="{Binding ElderCommand}"> 21 <TextBlock Text="老いる" /> 22 </Button> 23 </StackPanel> 24</Window>

cs

1using System.Windows; 2using Prism.Mvvm; 3using Reactive.Bindings; 4using Reactive.Bindings.Extensions; 5 6namespace Questions250717 7{ 8 public class Person : BindableBase 9 { 10 public int Age1 { get; set; } 11 12 public int Age2 { get => _Age2; set => SetProperty(ref _Age2, value); } 13 private int _Age2; 14 15 public ReactivePropertySlim<int> Age3 { get; } 16 17 public Person() 18 { 19 Age1 = 55; 20 Age2 = 55; 21 Age3 = new ReactivePropertySlim<int>(55); 22 } 23 24 public void Younger() 25 { 26 //Age1--; 27 Age2--; 28 Age3.Value--; 29 } 30 31 public void Elder() 32 { 33 //Age1++; 34 Age2++; 35 Age3.Value++; 36 } 37 } 38 public class PersonViewModel : BindableBase 39 { 40 public ReactiveProperty<int> Age1 { get; } 41 public ReactiveProperty<int> Age2 { get; } 42 public ReactiveProperty<int> Age3 { get; } 43 44 public ReactiveCommand YoungerCommand { get; } 45 public ReactiveCommand ElderCommand { get; } 46 47 private readonly Person person; 48 49 public PersonViewModel(Person person) 50 { 51 this.person = person; 52 Age1 = ReactiveProperty.FromObject(this.person, x => x.Age1); 53 Age2 = this.person.ToReactivePropertyAsSynchronized(x => x.Age2); 54 Age3 = this.person.Age3.ToReactiveProperty(); 55 56 YoungerCommand = new ReactiveCommand().WithSubscribe(() => 57 { 58 Age1.Value--; 59 this.person.Younger(); 60 }); 61 ElderCommand = new ReactiveCommand().WithSubscribe(() => 62 { 63 Age1.Value++; 64 this.person.Elder(); 65 }); 66 } 67 } 68 public partial class MainWindow : Window 69 { 70 public MainWindow() 71 { 72 InitializeComponent(); 73 DataContext = new PersonViewModel(new Person()); 74 } 75 } 76}

投稿2020/04/01 09:29

編集2023/07/21 09:24
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tohooky

2020/04/01 23:28

ご回答ありがとうございます! Age2方式を実装して、Ageの変更がViewに反映されることを確認できました。 Person.csを以下のように変更しました。 private int age; public int Age { get { return age; } set { SetProperty(ref age, value); } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問