前提
WPF、Livetを使用してデスクトップアプリを作っています。
ObservableCollectionを使用したBindingで気になる挙動があったのでお知恵をお借りしたいです。
発生している問題・エラーメッセージ
ListBoxにObservableCollectionをバインドし、DataTemplateで要素を編集できるようにしました。
またComboBoxを用意し、同じコレクションをバインドし、DataTemplateで要素を見れるようにしたのですが、ListBoxで要素を変更した際にComboBoxの表示も変わってしまいます。
左のListBoxで「hogehoge」を追記。すると右のComboBoxの文字列も反映される。
挙動自体は私が想定していた通りなので問題は無いのですが、要素元のクラスのプロパティは全て自動プロパティで実装しており変更通知などがされません。
しかしどちらとも変更が反映されているため、なぜこの様な挙動になるか気になり質問を投稿させていただきました。
該当のソースコード
MainWindow.xaml
XAML
1<Window x:Class="My_Livet_Template_Project2.Views.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors" 5 xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" 6 xmlns:v="clr-namespace:My_Livet_Template_Project2.Views" 7 xmlns:vm="clr-namespace:My_Livet_Template_Project2.ViewModels" 8 Title="MainWindow" Width="500" Height="350"> 9 10 <Window.DataContext> 11 <vm:MainWindowViewModel/> 12 </Window.DataContext> 13 14 <behaviors:Interaction.Triggers> 15 <behaviors:EventTrigger EventName="Loaded"> 16 <l:LivetCallMethodAction MethodName="Initialize" MethodTarget="{Binding}"/> 17 </behaviors:EventTrigger> 18 <behaviors:EventTrigger EventName="Closed"> 19 <l:DataContextDisposeAction/> 20 </behaviors:EventTrigger> 21 </behaviors:Interaction.Triggers> 22 23 <Grid> 24 <Grid.ColumnDefinitions> 25 <ColumnDefinition Width="1*"/> 26 <ColumnDefinition Width="1*"/> 27 </Grid.ColumnDefinitions> 28 29 <ListBox Name="listBox" ItemsSource="{Binding Settings}" HorizontalContentAlignment="Stretch"> 30 <ListBox.ItemTemplate> 31 <DataTemplate> 32 <StackPanel> 33 <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Margin="4"/> 34 <Slider Value="{Binding Item1}" Margin="4"/> 35 </StackPanel> 36 </DataTemplate> 37 </ListBox.ItemTemplate> 38 </ListBox> 39 40 <ComboBox ItemsSource="{Binding Settings}" SelectedIndex="0" VerticalAlignment="Top" Grid.Column="1" Margin="0,110,0,0"> 41 <ComboBox.ItemTemplate> 42 <DataTemplate> 43 <StackPanel> 44 <TextBlock Text="{Binding Name, StringFormat=Name: {0}}"/> 45 <TextBlock Text="{Binding Item1, StringFormat=Item1: {0}}"/> 46 </StackPanel> 47 </DataTemplate> 48 </ComboBox.ItemTemplate> 49 </ComboBox> 50 51 <Button Content="Button" HorizontalAlignment="Center" Margin="0,200,0,0" VerticalAlignment="Top" Grid.Column="1"> 52 <behaviors:Interaction.Triggers> 53 <behaviors:EventTrigger EventName="Click"> 54 <l:LivetCallMethodAction MethodName="AppendName" 55 MethodParameter="{Binding SelectedIndex, ElementName=listBox}" 56 MethodTarget="{Binding}"/> 57 </behaviors:EventTrigger> 58 </behaviors:Interaction.Triggers> 59 </Button> 60 </Grid> 61</Window> 62
MainWindowViewModel.cs
C#
1using Livet; 2using My_Livet_Template_Project2.Models; 3using System.Collections.ObjectModel; 4 5namespace My_Livet_Template_Project2.ViewModels 6{ 7 public class MainWindowViewModel : ViewModel 8 { 9 private ObservableCollection<Setting> _settings = new(); 10 11 public ObservableCollection<Setting> Settings 12 { 13 get => _settings; 14 set => RaisePropertyChangedIfSet(ref _settings, value); 15 } 16 17 public void Initialize() 18 { 19 Settings.Add(new()); 20 } 21 22 public void AppendName(int index) 23 { 24 if (index == -1) 25 return; 26 27 Settings[index].Name += "追記"; 28 } 29 } 30} 31
Setting.cs
C#
1namespace My_Livet_Template_Project2.Models 2{ 3 public class Setting 4 { 5 public string Name { get; set; } = "デフォルト"; 6 public int Item1 { get; set; } 7 8 //private string _name = "デフォルト"; 9 //public string Name 10 //{ 11 // get => _name; 12 // set => _name = value; 13 //} 14 } 15} 16
試したこと
- ViewModel側で何か追記してみる(AppendName関数) → しっかり追記されているが、UI側では変わっていない
- 要素クラスのプロパティを省略せずに書く(Setting.csにてコメントアウトしている部分) → 最初の挙動と同じ
- SettingクラスにNotificationObjectを継承してみる → ComboBoxには反映されない
- SettingクラスにNotifcationObjectを継承し、プロパティで変更通知をする → 最初の挙動と同じ
補足情報(FW/ツールのバージョンなど)
Microsoft Visual Studio Community 2022 Version 17.5.2
C#10
LivetCask 4.0.2

回答1件
あなたの回答
tips
プレビュー