using System.Collections.ObjectModel;
namespace MultiSelectTreeViewDemo
{
public sealed class DemoViewModel
{
public ObservableCollection<FoodItem> FoodGroups { get; set; }
public DemoViewModel()
{
var redMeat = new FoodItem { Name = "Reds" };
redMeat.Add(new FoodItem { Name = "Beef" });
redMeat.Add(new FoodItem { Name = "Buffalo" });
redMeat.Add(new FoodItem { Name = "Lamb" });
var whiteMeat = new FoodItem { Name = "Whites" };
whiteMeat.Add(new FoodItem { Name = "Chicken" });
whiteMeat.Add(new FoodItem { Name = "Duck" });
whiteMeat.Add(new FoodItem { Name = "Pork" });
var meats = new FoodItem { Name = "Meats", Children = { redMeat, whiteMeat } };
var veggies = new FoodItem { Name = "Vegetables" };
veggies.Add(new FoodItem { Name = "Potato" });
veggies.Add(new FoodItem { Name = "Corn" });
veggies.Add(new FoodItem { Name = "Spinach" });
var fruits = new FoodItem { Name = "Fruits" };
fruits.Add(new FoodItem { Name = "Apple" });
fruits.Add(new FoodItem { Name = "Orange" });
fruits.Add(new FoodItem { Name = "Pear" });
FoodGroups = new ObservableCollection<FoodItem> { meats, veggies, fruits };
}
}
public sealed class FoodItem
{
public string Name { get; set; }
public ObservableCollection<FoodItem> Children { get; set; }
public FoodItem()
{
Children = new ObservableCollection<FoodItem>();
}
public void Add(FoodItem item)
{
Children.Add(item);
}
}
}
型 下面是MainWindow代码背后的按钮点击处理程序,它显示了MessageBox中的选择。
private void GetSelectionsButton_OnClick(object sender, RoutedEventArgs e)
{
var selectedMesg = "";
var selectedItems = multiSelectTreeView.SelectedItems;
if (selectedItems.Count > 0)
{
selectedMesg = selectedItems.Cast<FoodItem>()
.Where(modelItem => modelItem != null)
.Aggregate(selectedMesg, (current, modelItem) => current + modelItem.Name + Environment.NewLine);
}
else
selectedMesg = "No selected items!";
MessageBox.Show(selectedMesg, "MultiSelect TreeView Demo", MessageBoxButton.OK);
}
private void SelectedItemChangedInternal(TreeViewItem tvItem)
{
// Clear all previous selected item states if ctrl is NOT being held down
if (!IsCtrlPressed)
{
var items = GetTreeViewItems(this, true);
foreach (var treeViewItem in items)
{
SetIsItemSelected(treeViewItem, false);
}
}
// Is this an item range selection?
if (IsShiftPressed && _lastItemSelected != null)
{
var items = GetTreeViewItemRange(_lastItemSelected, tvItem);
if (items.Count > 0)
{
foreach (var treeViewItem in items)
SetIsItemSelected(treeViewItem, true);
}
}
// Otherwise, individual selection
else
{
SetIsItemSelected(tvItem, !GetIsItemSelected(tvItem));
_lastItemSelected = tvItem;
}
}
5条答案
按热度按时间yruzcnhs1#
我有一个SoMoS实现的变体,它使用在基本TreeView控件的派生上声明的attached属性来跟踪TreeViewItem的选择状态。这使得选择跟踪在TreeViewItem元素本身上,而不在树视图所呈现的模型对象上。
这是新的TreeView类派生。
字符串
这里是XAML。请注意,突出的部分是使用MultiSelectTreeViewItemStyle中新的'IsItemSelected'附加属性来替换使用单数'IsSelected'属性的两个触发器,以实现可视状态。
另外请注意,我没有将新的TreeView控件聚合到UserControl中。
型
这里有一个俗气的视图模型来驱动它(用于演示目的)。
型
下面是MainWindow代码背后的按钮点击处理程序,它显示了MessageBox中的选择。
型
希望这对你有帮助。
wdebmtf22#
当我考虑重写控件的基本行为时,比如树视图,我总是喜欢考虑与我的决定相关的可用性和工作量。
在树视图的特定情况下,我发现切换到列表视图并结合零个、一个或多个控件可以形成更有用的解决方案,而且通常更容易实现。
例如,考虑常见的打开对话框或Windows资源管理器应用程序。
ugmeyewa3#
我已经简化了这个任务,在每个treeviewitem的文本之前添加了一个复选框。
所以,我创建了一个dockpanel,里面有两个项目:checkbox + textblock。
所以...
XAML
字符串
CS
型
然后您可以访问复选框值:
型
如果你不需要任何复杂的东西,这是一个简单的方法。
yws3nbqq4#
我终于结束了我自己的CustomControl编码包含一个TreeView里面.基于其他人的工作的关键功能驻留在使所有项目的模型的TreeView继承接口ISelectable:
字符串
这样,我们将有一个新的'IsSelected'属性,它与TreeViewItem IsSelected无关。我们只需要设置树的样式,使其处理模型IsSelected属性。下面的代码(它使用http://code.google.com/p/gong-wpf-dragdrop/上的拖放库):
XAML
型
C#:
型
vwhgwdsa5#
@Nishan Hossepian的答案很好,但最好像这样重写
SelectedItemChangedInternal
方法:字符串