我有一個基於TreeView
自定義控件,需要添加到基於TreeViewItem
CheckBox
綁定到CheckedTreeViewItem.IsEnabled
財產我CheckedTreeViewItem
添加複選框。 我嘗試添加CheckBox
到TreeView.ItemTemplate
,但如果這樣寫:如何在CustomControl基於WPF的TreeView
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<CheckBox IsChecked="{Binding Path=IsSelected,Mode=TwoWay}" Name="ItemCheckBox" Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
CheckBox
只出現在第一CheckedTreeViewItem
。如果我寫這樣的
:
但中只有複選框可見。
更新:對不起,沒有添加代碼,我現在不是說這是如此重要。我用CheckedObjects邏輯編寫TreeView,因爲我無法在我的項目中將我的對象包裹在ViewModel中。我已經用該邏輯編寫了ListBox,對我來說非常有用。
XAML:
<TreeView x:Class="TestControlsLibrary.CheckedTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:testControlsLibrary="clr-namespace:TestControlsLibrary"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<!-- Need specify that for each CheckedTreeViewItem need draw CheckBox, with possibility to use DisplayMemberPath for content in item-->
</TreeView>
後臺代碼:
public partial class CheckedTreeView : TreeView
{
public CheckedTreeView()
{
InitializeComponent();
}
public static readonly DependencyProperty CheckedItemsProperty;
public static readonly RoutedEvent CheckedChangedEvent;
public static readonly RoutedEvent ItemCheckedEvent;
public static readonly RoutedEvent ItemUnCheckedEvent;
public static readonly RoutedEvent CheckedItemsChangedEvent;
static CheckedTreeView()
{
CheckedItemsProperty = DependencyProperty.Register("CheckedItems", typeof (IEnumerable), typeof (CheckedTreeView),
new FrameworkPropertyMetadata(new ArrayList(), new PropertyChangedCallback(OnCheckedItemsChanged)));
CheckedChangedEvent = EventManager.RegisterRoutedEvent("CheckedChanged", RoutingStrategy.Bubble,
typeof (RoutedPropertyChangedEventHandler<bool>), typeof (CheckedTreeViewItem));
ItemCheckedEvent = EventManager.RegisterRoutedEvent("ItemChecked", RoutingStrategy.Bubble,
typeof (RoutedPropertyChangedEventHandler<object>), typeof (CheckedTreeView));
ItemUnCheckedEvent = EventManager.RegisterRoutedEvent("ItemUnChecked", RoutingStrategy.Bubble,
typeof (RoutedPropertyChangedEventHandler<object>), typeof (CheckedTreeView));
CheckedItemsChangedEvent = EventManager.RegisterRoutedEvent("CheckedItemsChanged", RoutingStrategy.Bubble,
typeof (RoutedPropertyChangedEventHandler<IEnumerable>), typeof (CheckedTreeView));
EventManager.RegisterClassHandler(typeof (CheckedTreeView), CheckedTreeViewItem.CheckedEvent,
new RoutedEventHandler(checkedEventHandler));
EventManager.RegisterClassHandler(typeof (CheckedTreeView), CheckedTreeViewItem.UnCheckedEvent,
new RoutedEventHandler(unCheckedEventHandler));
}
private static void checkedEventHandler(object sender, RoutedEventArgs e)
{
var checkedTreeView = (CheckedTreeView) sender;
var item = (CheckedTreeViewItem) e.OriginalSource;
var collection = checkedTreeView.CheckedItems;
collection.Add(checkedTreeView.Items);
checkedTreeView.CheckedItems = new ArrayList(collection);
}
private static void unCheckedEventHandler(object sender, RoutedEventArgs e)
{
var checkedTreeView = (CheckedTreeView) sender;
var item = (CheckedTreeViewItem) e.OriginalSource;
var collection = checkedTreeView.CheckedItems;
collection.Remove(item.Items);
checkedTreeView.CheckedItems = new ArrayList(collection);
}
public event RoutedPropertyChangedEventHandler<IEnumerable> CheckedItemsChanged
{
add { AddHandler(CheckedItemsChangedEvent, value); }
remove { RemoveHandler(CheckedItemsChangedEvent, value); }
}
public event RoutedPropertyChangedEventHandler<object> ItemChecked
{
add { AddHandler(ItemCheckedEvent, value); }
remove { RemoveHandler(ItemCheckedEvent, value); }
}
public event RoutedPropertyChangedEventHandler<object> ItemUnChecked
{
add { AddHandler(ItemUnCheckedEvent, value); }
remove { RemoveHandler(ItemUnCheckedEvent, value); }
}
public IEnumerable CheckedItems
{
get { return (IEnumerable) GetValue(CheckedItemsProperty); }
set { SetValue(CheckedItemsProperty, value); }
}
private static void OnCheckedItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var checkedTreeView = (CheckedTreeView) sender;
var args = new RoutedPropertyChangedEventArgs<IEnumerable>((IEnumerable) e.OldValue, (IEnumerable) e.NewValue);
args.RoutedEvent = CheckedTreeView.CheckedItemsChangedEvent;
checkedTreeView.RaiseEvent(args);
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return (item is CheckedTreeViewItem);
}
protected override DependencyObject GetContainerForItemOverride()
{
return new CheckedTreeViewItem();
}
}
public class CheckedTreeViewItem : TreeViewItem
{
public static DependencyProperty IsCheckedProperty;
public static readonly RoutedEvent CheckChangedEvent;
public static readonly RoutedEvent CheckedEvent;
public static readonly RoutedEvent UnCheckedEvent;
public bool? IsChecked
{
get { return (bool?) GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
public event RoutedPropertyChangedEventHandler<bool> CheckChanged
{
add { AddHandler(CheckChangedEvent, value); }
remove { RemoveHandler(CheckChangedEvent, value); }
}
static CheckedTreeViewItem()
{
IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof (bool?), typeof (CheckedTreeViewItem),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnCheckChanged)));
CheckChangedEvent = EventManager.RegisterRoutedEvent("CheckChanged", RoutingStrategy.Bubble,
typeof (RoutedPropertyChangedEventHandler<bool>), typeof (CheckedTreeViewItem));
CheckedEvent = EventManager.RegisterRoutedEvent("Checked", RoutingStrategy.Bubble, typeof (RoutedEventHandler),
typeof (CheckedTreeViewItem));
UnCheckedEvent = EventManager.RegisterRoutedEvent("UnChecked", RoutingStrategy.Bubble, typeof (RoutedEventHandler),
typeof (CheckedTreeViewItem));
}
private static void OnCheckChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var CheckedTreeViewItem = (CheckedTreeViewItem) sender;
var oldValue = (bool?) e.OldValue;
var newValue = (bool?) e.NewValue;
if ((bool) e.NewValue && !(bool) e.OldValue)
{
var argch = new RoutedEventArgs(CheckedTreeViewItem.CheckedEvent);
CheckedTreeViewItem.RaiseEvent(argch);
}
else if (!(bool) e.NewValue && (bool) e.OldValue)
{
var argun = new RoutedEventArgs(CheckedTreeViewItem.UnCheckedEvent);
CheckedTreeViewItem.RaiseEvent(argun);
}
var args = new RoutedPropertyChangedEventArgs<bool?>(oldValue, newValue);
args.RoutedEvent = CheckedTreeViewItem.CheckChangedEvent;
CheckedTreeViewItem.RaiseEvent(args);
}
private static IEnumerable<CheckedTreeViewItem> GetListItems(CheckedTreeViewItem treeViewItem)
{
foreach (var item in treeViewItem.Items)
{
yield return (CheckedTreeViewItem)treeViewItem.ItemContainerGenerator.ContainerFromItem(item);
}
}
private void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
{
if (value == IsChecked)
return;
IsChecked = value;
if (updateChildren && IsChecked.HasValue)
GetListItems(this).ToList().ForEach(c => c.SetIsChecked(IsChecked, true, false));
if (updateParent && this.Parent != null)
(this.Parent as CheckedTreeViewItem).VerifyCheckState();
// this.OnPropertyChanged("IsChecked");
}
private void VerifyCheckState()
{
bool? state = null;
foreach (var item in GetListItems(this))
{
bool? current = item.IsChecked;
//if (i == 0)
//{
// state = current;
//}
//else if (state != current)
//{
// state = null;
// break;
//}
}
this.SetIsChecked(state, false, true);
}
}
}
你不需要覆蓋樹型視圖的'Template'。你爲什麼這樣做? –
您需要使用CheckBox編寫HierarchicalDataTemplate.ItemTemplate。 –
@RohitVats因爲這段代碼可以很好地處理'ListBox',我仍然可以使用DisplayMemberPath並通過每個ListBoxItem上的CheckBox和Content來獲取所需的視圖。但可能是我走錯了路。 – Nightingale