ViewModelを使用してWPFツリーに動的にデータを入力しようとしていますが、何らかの理由で機能していません。バインディングが適切でないか、コードビハインドのどこかで混乱しています。
これが私が持っているもののサンプルです。XAMLでは、TreeViewを次のように定義します...
<TreeView DockPanel.Dock="Left" Width="200" DataContext="{Binding MessageTree}" ItemsSource="{Binding MessageTree}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="viewModel:Mail" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Subject}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
CodeBehingでは...
private Mail MessageTree { get; set; }
と
using (var mail = new MailParser())
{
int count = mail.GetMessageCount(DateTime.Today.AddDays(-10), DateTime.Today.AddDays(1));
MessageTree = new Mail();
for (int i = count - 1; i >= 0; i--)
{
MailMessage msg = mail.RetrieveMessage(i);
if (msg != null)
{
MessageTree.Add(msg);
}
if (backgroundWorker != null)
{
decimal perc = (100.0m - (((i + 1.0m)*100.0m)/count));
backgroundWorker.ReportProgress((int) perc, "Recebendo mensagens... " + perc.ToString("N2") + "%");
if (backgroundWorker.CancellationPending)
{
e.Cancel = true;
break;
}
}
}
}
メールは次のように定義されます
public sealed class Mail : INotifyPropertyChanged
{
private readonly ObservableCollection<Mail> _children;
private readonly MailMessage _msg;
private readonly Mail _parent;
private bool _isExpanded;
private bool _isSelected;
public Mail()
{
_msg = new MailMessage {Subject = "Empty"};
_parent = null;
_children = new ObservableCollection<Mail>();
}
public Mail(MailMessage msg, Mail parent = null)
{
_msg = msg;
_parent = parent;
_children = new ObservableCollection<Mail>();
}
public IEnumerable<Mail> Children
{
get { return _children; }
}
public string Subject
{
get { return _msg.Subject; }
}
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (value != _isExpanded)
{
_isExpanded = value;
OnPropertyChanged();
}
if (_isExpanded && _parent != null)
_parent.IsExpanded = true;
}
}
public bool IsSelected
{
get { return _isSelected; }
set
{
if (value != _isSelected)
{
_isSelected = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void Add(MailMessage msg)
{
_children.Add(new Mail(msg, this));
OnPropertyChanged("Children");
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
オンラインで見つけた例とあまりに違うものが見つからないので、うまくいきません。Addメソッドは不完全です。コレクションに追加するか、コレクションメンバーの1つのコレクションに追加するかを決定するロジックが必要ですが、すべてのメールオブジェクトがコレクションに追加されていますが、ツリー表示。
私が見逃している完全に明白なことは何ですか?コレクションにアイテムを追加するときに、TreeViewが自動的に更新されるべきではありませんか?
私が欲しいのは、TreeViewがMessageTreeプロパティの子とそれらの子の子を表示することです。