0
我有一個樹視圖表示,其中每個項目都有一個複選框的項目的層次結構。我想在樹形視圖下面顯示一個包含所有選中項的列表框。如何使用MVVM模式實現這樣的功能?WPF Treeview和列表框同步
在此先感謝 盧卡斯Glaz
我有一個樹視圖表示,其中每個項目都有一個複選框的項目的層次結構。我想在樹形視圖下面顯示一個包含所有選中項的列表框。如何使用MVVM模式實現這樣的功能?WPF Treeview和列表框同步
在此先感謝 盧卡斯Glaz
下面是一個例子:
視圖模型
public class TreeNodeViewModel : ViewModelBase
{
#region Constructors
public TreeNodeViewModel(string text, params TreeNodeViewModel[] nodes)
: this(text, new ObservableCollection<TreeNodeViewModel>(nodes))
{
}
public TreeNodeViewModel(string text, ObservableCollection<TreeNodeViewModel> nodes)
{
Text = text;
Nodes = nodes;
foreach (var node in Nodes)
{
node.Parent = this;
}
Nodes.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Nodes_CollectionChanged);
}
#endregion
#region Private methods
private void Nodes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (var node in e.OldItems.Cast<TreeNodeViewModel>())
{
node.Parent = null;
}
foreach (var node in e.NewItems.Cast<TreeNodeViewModel>())
{
node.Parent = this;
}
OnPropertyChanged("CheckedNodes");
}
private void NotifyParent()
{
if (Parent != null)
{
Parent.OnPropertyChanged("CheckedNodes");
Parent.NotifyParent();
}
}
#endregion
#region Private data
private string _text;
private bool _isChecked;
private TreeNodeViewModel _parent;
#endregion
#region Public properties
public string Text
{
get { return _text; }
set
{
if (value != _text)
{
_text = value;
OnPropertyChanged("Text");
}
}
}
public bool IsChecked
{
get { return _isChecked; }
set
{
if (value != _isChecked)
{
_isChecked = value;
NotifyParent();
OnPropertyChanged("IsChecked");
}
}
}
public ObservableCollection<TreeNodeViewModel> Nodes { get; private set; }
public IEnumerable<TreeNodeViewModel> CheckedNodes
{
get
{
foreach (var node in Nodes)
{
if (node.IsChecked)
yield return node;
foreach (var child in node.CheckedNodes)
{
yield return child;
}
}
}
}
public TreeNodeViewModel Parent
{
get { return _parent; }
private set
{
if (value != _parent)
{
_parent = value;
OnPropertyChanged("Parent");
}
}
}
#endregion
}
XAML
<TreeView Grid.Row="0" ItemsSource="{Binding Nodes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<ListBox Grid.Row="1" ItemsSource="{Binding CheckedNodes}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
代碼隱藏
this.DataContext = new TreeNodeViewModel(
null,
new TreeNodeViewModel(
"1",
new TreeNodeViewModel(
"1.1",
new TreeNodeViewModel("1.1.1"),
new TreeNodeViewModel("1.1.2")),
new TreeNodeViewModel("1.2")),
new TreeNodeViewModel(
"2",
new TreeNodeViewModel("2.1"),
new TreeNodeViewModel(
"2.2",
new TreeNodeViewModel("2.2.1"))));
請注意,這是一個相當幼稚的做法,很容易就會被提高...例如,檢查節點的整個列表重新評估每一個節點被選中/取消的時候,這可能導致糟糕表現爲一個大的TreeView
謝謝您的非常詳細,容易理解的例子:) – GUZ 2009-10-13 12:56:17