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

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

新規登録して質問してみよう
ただいま回答率
86.12%
MVVM

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

WPF

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

解決済

WPFで入れ子になっている要素の変更を反映させたいです

terullet
terullet

総合スコア2

MVVM

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

WPF

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

2回答

1リアクション

1クリップ

386閲覧

投稿2022/08/30 03:05

解決したいこと

WPFにおいて,入れ子になっているListBoxにViewModel側で要素を追加しても,画面に反映されません.
どうしたらよいか,解決方法を教えてください.よろしくお願いします.

発生している問題の詳細

図にすると下記のような感じです.

BindingDescription.png

デバッグでWPFビジュアライザーから確認したところ,
WrapperControl内のElementControlsItemsSourceObservableCollenction<ElementViewModel>が入っていることは確認できたのですが,
画面には反映されていませんでした.

ソースコード

xml:MainWindow.xaml

<Window x:Class="ListBoxExperiment.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ListBoxExperiment" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.DataContext> <local:MainViewModel/> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ListBox Grid.Row="0" x:Name="WrapperControls" ItemsSource="{Binding Wrappers, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"> <ListBox.ItemTemplate> <DataTemplate> <local:WrapperControl/> </DataTemplate> </ListBox.ItemTemplate> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> </Style> </ListBox.ItemContainerStyle> </ListBox> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Button Content="Wrapperを追加" Grid.Column="0" Command="{Binding AddWrapper}"/> <Button Content="先頭のWrapperにElementを追加" Grid.Column="1" Command="{Binding AddElement}"/> </Grid> <!-- デバッグ時の一時停止用のボタンです. ブレークポイントを設定しているだけの関数をコードビハインドに書いています. --> <Button Content="ブレイク" Grid.Row="2" Click="Break"/> </Grid> </Window>

xml:WrapperControl.xaml

<UserControl x:Class="ListBoxExperiment.WrapperControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ListBoxExperiment" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.DataContext> <local:WrapperViewModel/> </UserControl.DataContext> <Grid> <ListBox x:Name="ElementControls" ItemsSource="{Binding Elements, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"> <ListBox.ItemTemplate> <DataTemplate> <local:ElementControl/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </UserControl>

xml:ElementControl.xaml

<UserControl x:Class="ListBoxExperiment.ElementControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ListBoxExperiment" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.DataContext> <local:ElementViewModel/> </UserControl.DataContext> <Grid> <TextBlock Text="{Binding AddedAt, StringFormat=Created at {0:yyyy/MM/dd-HH:mm:ss}}"/> </Grid> </UserControl>

cs:MainViewModel.cs

using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Ink; using System.Windows.Input; namespace ListBoxExperiment { public class MainViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; public ObservableCollection<WrapperViewModel> Wrappers { get; private set; } public DelegateCommand AddElement { get; private set; } public DelegateCommand AddWrapper { get; private set; } public MainViewModel() { this.Wrappers = new ObservableCollection<WrapperViewModel>(); this.Wrappers.Add(new WrapperViewModel()); this.Wrappers[0].PropertyChanged += (s, e) => this.PropertyChanged?.Invoke(s, new PropertyChangedEventArgs(nameof(Wrappers))); this.AddElement = new DelegateCommand(() => this.Wrappers[0].Elements.Add(new ElementViewModel()), () => true); this.AddWrapper = new DelegateCommand(() => this.Wrappers.Add(new WrapperViewModel()), () => true); } } public class DelegateCommand : ICommand { public event EventHandler? CanExecuteChanged; public bool CanExecute(object? parameter) => this._canExecute(); public void Execute(object? parameter) => this._execute(); private Action _execute; private Func<bool> _canExecute; public DelegateCommand(Action execute, Func<bool> canExecute) { _execute = execute; _canExecute = canExecute; } } }

cs:WrapperViewModel.cs

using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ListBoxExperiment { public class WrapperViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; public ObservableCollection<ElementViewModel> Elements { get; private set; } public WrapperViewModel() { this.Elements = new ObservableCollection<ElementViewModel>(); this.Elements.Add(new ElementViewModel()); this.Elements.CollectionChanged += (s, e) => this.PropertyChanged?.Invoke(s, new PropertyChangedEventArgs(nameof(Elements))); } } }

cs:ElementViewModel.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ListBoxExperiment { public class ElementViewModel { public DateTime AddedAt { get; private set; } public ElementViewModel() { this.AddedAt = DateTime.Now; } } }

試したこと

上記のコードのように,CollectionChangedPropertyChangedを登録したり,
WrapperViewModelPropertyChangedMainViewModelPropertyChangedを登録したりしてみたのですが,
うまくいきませんでした.

TN8001👍を押しています

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

MVVM

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

WPF

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