解決したいこと
WPFにおいて,入れ子になっているListBoxにViewModel側で要素を追加しても,画面に反映されません.
どうしたらよいか,解決方法を教えてください.よろしくお願いします.
発生している問題の詳細
図にすると下記のような感じです.
デバッグでWPFビジュアライザーから確認したところ,
WrapperControl
内のElementControls
のItemsSource
にObservableCollenction<ElementViewModel>
が入っていることは確認できたのですが,
画面には反映されていませんでした.
ソースコード
xml:MainWindow.xaml
1<Window x:Class="ListBoxExperiment.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:ListBoxExperiment" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Window.DataContext> 10 <local:MainViewModel/> 11 </Window.DataContext> 12 <Grid> 13 <Grid.RowDefinitions> 14 <RowDefinition/> 15 <RowDefinition Height="Auto"/> 16 <RowDefinition Height="Auto"/> 17 </Grid.RowDefinitions> 18 19 <ListBox 20 Grid.Row="0" 21 x:Name="WrapperControls" 22 ItemsSource="{Binding Wrappers, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"> 23 <ListBox.ItemTemplate> 24 <DataTemplate> 25 <local:WrapperControl/> 26 </DataTemplate> 27 </ListBox.ItemTemplate> 28 <ListBox.ItemContainerStyle> 29 <Style TargetType="{x:Type ListBoxItem}"> 30 <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 31 <Setter Property="VerticalContentAlignment" Value="Stretch"/> 32 </Style> 33 </ListBox.ItemContainerStyle> 34 </ListBox> 35 36 <Grid Grid.Row="1"> 37 <Grid.ColumnDefinitions> 38 <ColumnDefinition/> 39 <ColumnDefinition/> 40 </Grid.ColumnDefinitions> 41 42 <Button 43 Content="Wrapperを追加" 44 Grid.Column="0" 45 Command="{Binding AddWrapper}"/> 46 47 <Button 48 Content="先頭のWrapperにElementを追加" 49 Grid.Column="1" 50 Command="{Binding AddElement}"/> 51 </Grid> 52 53 <!-- デバッグ時の一時停止用のボタンです. 54 ブレークポイントを設定しているだけの関数をコードビハインドに書いています. --> 55 <Button Content="ブレイク" Grid.Row="2" Click="Break"/> 56 </Grid> 57</Window>
xml:WrapperControl.xaml
1<UserControl x:Class="ListBoxExperiment.WrapperControl" 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 xmlns:local="clr-namespace:ListBoxExperiment" 7 mc:Ignorable="d" 8 d:DesignHeight="450" d:DesignWidth="800"> 9 <UserControl.DataContext> 10 <local:WrapperViewModel/> 11 </UserControl.DataContext> 12 <Grid> 13 <ListBox 14 x:Name="ElementControls" 15 ItemsSource="{Binding Elements, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"> 16 <ListBox.ItemTemplate> 17 <DataTemplate> 18 <local:ElementControl/> 19 </DataTemplate> 20 </ListBox.ItemTemplate> 21 </ListBox> 22 </Grid> 23</UserControl>
xml:ElementControl.xaml
1<UserControl x:Class="ListBoxExperiment.ElementControl" 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 xmlns:local="clr-namespace:ListBoxExperiment" 7 mc:Ignorable="d" 8 d:DesignHeight="450" d:DesignWidth="800"> 9 <UserControl.DataContext> 10 <local:ElementViewModel/> 11 </UserControl.DataContext> 12 <Grid> 13 <TextBlock Text="{Binding AddedAt, StringFormat=Created at {0:yyyy/MM/dd-HH:mm:ss}}"/> 14 </Grid> 15</UserControl>
cs:MainViewModel.cs
1using System; 2using System.Collections.Generic; 3using System.Collections.ObjectModel; 4using System.ComponentModel; 5using System.Linq; 6using System.Text; 7using System.Threading.Tasks; 8using System.Windows.Ink; 9using System.Windows.Input; 10 11namespace ListBoxExperiment 12{ 13 public class MainViewModel : INotifyPropertyChanged 14 { 15 public event PropertyChangedEventHandler? PropertyChanged; 16 17 public ObservableCollection<WrapperViewModel> Wrappers { get; private set; } 18 19 public DelegateCommand AddElement { get; private set; } 20 21 public DelegateCommand AddWrapper { get; private set; } 22 23 public MainViewModel() 24 { 25 this.Wrappers = new ObservableCollection<WrapperViewModel>(); 26 this.Wrappers.Add(new WrapperViewModel()); 27 this.Wrappers[0].PropertyChanged += (s, e) => this.PropertyChanged?.Invoke(s, new PropertyChangedEventArgs(nameof(Wrappers))); 28 this.AddElement = new DelegateCommand(() => this.Wrappers[0].Elements.Add(new ElementViewModel()), () => true); 29 this.AddWrapper = new DelegateCommand(() => this.Wrappers.Add(new WrapperViewModel()), () => true); 30 } 31 } 32 33 public class DelegateCommand : ICommand 34 { 35 public event EventHandler? CanExecuteChanged; 36 37 public bool CanExecute(object? parameter) => this._canExecute(); 38 39 public void Execute(object? parameter) => this._execute(); 40 41 private Action _execute; 42 private Func<bool> _canExecute; 43 44 public DelegateCommand(Action execute, Func<bool> canExecute) 45 { 46 _execute = execute; 47 _canExecute = canExecute; 48 } 49 } 50}
cs:WrapperViewModel.cs
1using System; 2using System.Collections.Generic; 3using System.Collections.ObjectModel; 4using System.ComponentModel; 5using System.Linq; 6using System.Text; 7using System.Threading.Tasks; 8 9namespace ListBoxExperiment 10{ 11 public class WrapperViewModel : INotifyPropertyChanged 12 { 13 public event PropertyChangedEventHandler? PropertyChanged; 14 15 public ObservableCollection<ElementViewModel> Elements { get; private set; } 16 17 public WrapperViewModel() 18 { 19 this.Elements = new ObservableCollection<ElementViewModel>(); 20 this.Elements.Add(new ElementViewModel()); 21 this.Elements.CollectionChanged += (s, e) => this.PropertyChanged?.Invoke(s, new PropertyChangedEventArgs(nameof(Elements))); 22 } 23 } 24}
cs:ElementViewModel.cs
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7namespace ListBoxExperiment 8{ 9 public class ElementViewModel 10 { 11 public DateTime AddedAt { get; private set; } 12 13 public ElementViewModel() 14 { 15 this.AddedAt = DateTime.Now; 16 } 17 } 18}
試したこと
上記のコードのように,CollectionChanged
にPropertyChanged
を登録したり,
WrapperViewModel
のPropertyChanged
にMainViewModel
のPropertyChanged
を登録したりしてみたのですが,
うまくいきませんでした.

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/08/30 21:45 編集