使用MVVM模式,我试图在XAML中构建一个TreeView,看起来像这样(注意括号内的项目实际上代表按钮):
- [Edit] [Delete] Location 1
- [Edit] [Delete] Location 1, Project 1
- [Edit] [Delete] Location 1, Project 2
- [Edit] [Delete] Location 1, Project 3
- [New Project]
- [Edit] [Delete] Location 2
- [Edit] [Delete] Location 2, Project 1
- [New Project]
- [Edit] [Delete] Location 3
- [Edit] [Delete] Location 3, Project 1
- [Edit] [Delete] Location 3, Project 2
- [New Project]
- [New Location]
这个想法是,TreeView中的每个节点在标题文本旁边都有两个按钮,用户可以单击它们来删除/编辑节点。然后,在每个项目"组"的底部,有一个[新建项目]按钮,可以点击该按钮向该"组"添加新项目。最后,在整个TreeView的底部有一个[New Location]按钮,这样就可以添加一个新的Location节点。
我有TreeView和[新位置]按钮正确布局,但不知道如何将[新项目]按钮添加到每个位置的项目组的底部。我试过使用多个嵌套的TreeView控件,但是分组和滚动似乎不像预期的那样起作用。
下面是我的MainPageView代码:<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="SilverlightApplication2.MainPageView"
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:silverlightApplication2="clr-namespace:SilverlightApplication2"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.DataContext>
<silverlightApplication2:MainPageViewModel/>
</UserControl.DataContext>
<StackPanel Orientation="Vertical">
<sdk:TreeView ItemsSource="{Binding Locations}" BorderBrush="Transparent">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Projects}">
<StackPanel Orientation="Horizontal">
<Button Margin="2">
<Image Source="edit.png"/>
<ToolTipService.ToolTip>
<ToolTip Content="Edit item"/>
</ToolTipService.ToolTip>
</Button>
<Button Margin="2">
<Image Source="delete.png"/>
<ToolTipService.ToolTip>
<ToolTip Content="Delete item"/>
</ToolTipService.ToolTip>
</Button>
<sdk:TreeViewItem Header="{Binding Name}"/>
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>
<Button Margin="30,0,0,0" Height="23" Width="23" HorizontalAlignment="Left">
<Image Source="green-plus-sign-md.png"></Image>
<ToolTipService.ToolTip>
<ToolTip Content="Add new location"/>
</ToolTipService.ToolTip>
</Button>
</StackPanel>
</UserControl>
下面是我的MainPageViewModel代码:
using System.Collections.ObjectModel;
namespace SilverlightApplication2
{
public class MainPageViewModel
{
#region Constructors
public MainPageViewModel()
{
this.Locations = new ObservableCollection<LocationViewModel>
{
new LocationViewModel
{
Name = "Location 1",
Projects = new ObservableCollection<ProjectViewModel>
{
new ProjectViewModel { Name = "Location 1 - Project 1"},
new ProjectViewModel { Name = "Location 1 - Project 2"},
new ProjectViewModel { Name = "Location 1 - Project 3"},
new ProjectViewModel { Name = "Location 1 - Project 4"},
}
},
new LocationViewModel
{
Name = "Location 2",
Projects = new ObservableCollection<ProjectViewModel>
{
new ProjectViewModel { Name = "Location 2 - Project 1"},
new ProjectViewModel { Name = "Location 2 - Project 2"}
}
},
new LocationViewModel
{
Name = "Location 3",
Projects = new ObservableCollection<ProjectViewModel>
{
new ProjectViewModel { Name = "Location 3 - Project 1"},
new ProjectViewModel { Name = "Location 3 - Project 2"},
new ProjectViewModel { Name = "Location 3 - Project 3"},
new ProjectViewModel { Name = "Location 3 - Project 4"},
new ProjectViewModel { Name = "Location 3 - Project 5"},
new ProjectViewModel { Name = "Location 3 - Project 6"},
new ProjectViewModel { Name = "Location 3 - Project 7"}
}
}
};
}
#endregion
#region Properties
public ObservableCollection<LocationViewModel> Locations { get; set; }
#endregion
}
}
这里是LocationViewModelCode:
using System.Collections.ObjectModel;
using Microsoft.Practices.Prism.ViewModel;
namespace SilverlightApplication2
{
public class LocationViewModel : NotificationObject
{
#region Properties
public string Name { get; set; }
public ObservableCollection<ProjectViewModel> Projects { get; set; }
#endregion
}
}
最后,ProjectViewModel代码:
namespace SilverlightApplication2
{
public class ProjectViewModel
{
#region Properties
public string Name { get; set; }
#endregion
}
}
正如你所看到的,我在Silverlight中这样做,但是如果有人知道如何做到这一点,WPF解决方案可能会同样好。
我也意识到,这可能可以很容易地完成代码隐藏,但我试图保持真实的MVVM模式,并找到一种方法来做这个纯粹在XAML。
谢谢你的帮助
我将泛化树节点的视图模型。
可能有IsLocation, IsProject和HasContent属性。
HasContent属性可以控制节点是否显示"New…"的链接。然后你可以在该链接的命令中检查它的类型。
如果你不想拥有IsLocation和IsProject,你可以为树节点使用一个抽象基类,并从它继承两个类型。两者对HasContent都有类似的逻辑,然后对'New'逻辑有不同的命令
也许重新考虑架构会有所帮助?
我个人认为"新项目"操作是对Location
对象的操作,而不是位于Projects
集合内的操作。在这种情况下,您的"新项目"按钮可能应该与Location
的根edit
和delete
按钮放在一起。
也许不是直接回答你的问题,而是一个侧面的方法。