removed original treeview control as now this is supported in the box with the latest windows sdk
This commit is contained in:
Родитель
67fe322707
Коммит
b33a775123
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "IntegerToIndentationConverter.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
|
||||
namespace TreeViewControl {
|
||||
|
||||
IntegerToIndentationConverter::IntegerToIndentationConverter()
|
||||
{
|
||||
//default
|
||||
indentMultiplier = 20;
|
||||
}
|
||||
|
||||
Object^ IntegerToIndentationConverter::Convert(Object^ value, TypeName targetType, Object^ parameter, String^ language)
|
||||
{
|
||||
Thickness indent(0);
|
||||
if (value != nullptr)
|
||||
{
|
||||
indent.Left = (int)value * indentMultiplier;
|
||||
return indent;
|
||||
}
|
||||
|
||||
return indent;
|
||||
}
|
||||
|
||||
Object^ IntegerToIndentationConverter::ConvertBack(Object^ value, TypeName targetType, Object^ parameter, String^ language)
|
||||
{
|
||||
throw ref new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace TreeViewControl {
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
public ref class IntegerToIndentationConverter sealed : Windows::UI::Xaml::Data::IValueConverter
|
||||
{
|
||||
public:
|
||||
property int IndentMultiplier
|
||||
{
|
||||
int get() { return indentMultiplier; };
|
||||
void set(int i) { indentMultiplier = i; };
|
||||
}
|
||||
|
||||
IntegerToIndentationConverter();
|
||||
|
||||
virtual Platform::Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Platform::Object^ parameter, Platform::String^ language);
|
||||
|
||||
virtual Platform::Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Platform::Object^ parameter, Platform::String^ language);
|
||||
private:
|
||||
int indentMultiplier;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "TreeNode.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Platform::Collections;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
|
||||
namespace TreeViewControl {
|
||||
|
||||
TreeNode::TreeNode()
|
||||
{
|
||||
childrenVector->VectorChanged += ref new VectorChangedEventHandler<TreeNode ^>(this, &TreeNode::ChildrenVectorChanged);
|
||||
}
|
||||
|
||||
void TreeNode::Append(Object^ value)
|
||||
{
|
||||
int count = childrenVector->Size;
|
||||
TreeNode^ targetNode = (TreeNode^)value;
|
||||
targetNode->ParentNode = this;
|
||||
childrenVector->Append(targetNode);
|
||||
|
||||
//If the count was 0 before we appended, then the HasItems property needs to change.
|
||||
if (count == 0)
|
||||
{
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems"));
|
||||
}
|
||||
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size"));
|
||||
}
|
||||
|
||||
void TreeNode::Clear()
|
||||
{
|
||||
int count = childrenVector->Size;
|
||||
TreeNode^ childNode;
|
||||
for (int i = 0; i < (int)Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)GetAt(i);
|
||||
childNode->ParentNode = nullptr;
|
||||
}
|
||||
|
||||
childrenVector->Clear();
|
||||
|
||||
//If the count was not 0 before we cleared, then the HasItems property needs to change.
|
||||
if (count != 0)
|
||||
{
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems"));
|
||||
}
|
||||
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size"));
|
||||
}
|
||||
|
||||
IBindableIterator^ TreeNode::First()
|
||||
{
|
||||
return dynamic_cast<IBindableIterator^>(childrenVector->First());
|
||||
}
|
||||
|
||||
Object^ TreeNode::GetAt(unsigned int index)
|
||||
{
|
||||
if ((int)index > -1 && index < childrenVector->Size)
|
||||
{
|
||||
return childrenVector->GetAt(index);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IBindableVectorView^ TreeNode::GetView()
|
||||
{
|
||||
return safe_cast<IBindableVectorView^>(childrenVector->GetView());
|
||||
}
|
||||
|
||||
bool TreeNode::IndexOf(Object^ value, unsigned int* index)
|
||||
{
|
||||
return childrenVector->IndexOf((TreeNode^)value, index);
|
||||
}
|
||||
|
||||
void TreeNode::InsertAt(unsigned int index, Object^ value)
|
||||
{
|
||||
if ((int)index > -1 && index <= childrenVector->Size)
|
||||
{
|
||||
int count = childrenVector->Size;
|
||||
TreeNode^ targetNode = (TreeNode^)value;
|
||||
targetNode->ParentNode = this;
|
||||
return childrenVector->InsertAt(index, (TreeNode^)value);
|
||||
|
||||
//If the count was 0 before we insert, then the HasItems property needs to change.
|
||||
if (count == 0)
|
||||
{
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems"));
|
||||
}
|
||||
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size"));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeNode::RemoveAt(unsigned int index)
|
||||
{
|
||||
if ((int)index > -1 && index < childrenVector->Size)
|
||||
{
|
||||
int count = childrenVector->Size;
|
||||
TreeNode^ targetNode = childrenVector->GetAt(index);
|
||||
targetNode->ParentNode = nullptr;
|
||||
childrenVector->RemoveAt(index);
|
||||
|
||||
//If the count was 1 before we remove, then the HasItems property needs to change.
|
||||
if (count == 1)
|
||||
{
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems"));
|
||||
}
|
||||
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size"));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeNode::RemoveAtEnd()
|
||||
{
|
||||
int count = childrenVector->Size;
|
||||
TreeNode^ targetNode = childrenVector->GetAt(childrenVector->Size - 1);
|
||||
targetNode->ParentNode = nullptr;
|
||||
childrenVector->RemoveAtEnd();
|
||||
|
||||
//If the count was 1 before we remove, then the HasItems property needs to change.
|
||||
if (count == 1)
|
||||
{
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems"));
|
||||
}
|
||||
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size"));
|
||||
}
|
||||
|
||||
void TreeNode::SetAt(unsigned int index, Object^ value)
|
||||
{
|
||||
if ((int)index > -1 && index <= childrenVector->Size)
|
||||
{
|
||||
childrenVector->GetAt(index)->ParentNode = nullptr;
|
||||
TreeNode^ targetNode = (TreeNode^)value;
|
||||
targetNode->ParentNode = this;
|
||||
return childrenVector->SetAt(index, targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeNode::ChildrenVectorChanged(IObservableVector<TreeNode^>^ sender, IVectorChangedEventArgs^ e)
|
||||
{
|
||||
VectorChanged(this, e);
|
||||
}
|
||||
|
||||
unsigned int TreeNode::Size::get()
|
||||
{
|
||||
return childrenVector->Size;
|
||||
}
|
||||
|
||||
Object^ TreeNode::Data::get()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
void TreeNode::Data::set(Object^ value)
|
||||
{
|
||||
data = value;
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Data"));
|
||||
}
|
||||
|
||||
TreeNode^ TreeNode::ParentNode::get()
|
||||
{
|
||||
return parentNode;
|
||||
}
|
||||
|
||||
void TreeNode::ParentNode::set(TreeNode^ value)
|
||||
{
|
||||
parentNode = value;
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("ParentNode"));
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Depth"));
|
||||
}
|
||||
|
||||
bool TreeNode::IsExpanded::get()
|
||||
{
|
||||
return isExpanded;
|
||||
}
|
||||
|
||||
void TreeNode::IsExpanded::set(bool value)
|
||||
{
|
||||
isExpanded = value;
|
||||
this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("IsExpanded"));
|
||||
}
|
||||
|
||||
bool TreeNode::HasItems::get()
|
||||
{
|
||||
return (Size != 0);
|
||||
}
|
||||
|
||||
int TreeNode::Depth::get()
|
||||
{
|
||||
TreeNode^ ancestorNode = this;
|
||||
int depth = -1;
|
||||
while ((ancestorNode->ParentNode) != nullptr)
|
||||
{
|
||||
depth++;
|
||||
ancestorNode = ancestorNode->ParentNode;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace TreeViewControl {
|
||||
/// <summary>
|
||||
/// The TreeNode class implements the hierarchical layout for the TreeView.
|
||||
/// It also holds the data that will be bound to in the item template.
|
||||
/// </summary>
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
public ref class TreeNode sealed : Windows::UI::Xaml::Interop::IBindableObservableVector, Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
public:
|
||||
TreeNode();
|
||||
|
||||
virtual void Append(Object^ value);
|
||||
|
||||
virtual void Clear();
|
||||
|
||||
virtual Windows::UI::Xaml::Interop::IBindableIterator^ First();
|
||||
|
||||
virtual Object^ GetAt(unsigned int index);
|
||||
|
||||
virtual Windows::UI::Xaml::Interop::IBindableVectorView^ GetView();
|
||||
|
||||
virtual bool IndexOf(Object^ value, unsigned int* index);
|
||||
|
||||
virtual void InsertAt(unsigned int index, Object^ value);
|
||||
|
||||
virtual void RemoveAt(unsigned int index);
|
||||
|
||||
virtual void RemoveAtEnd();
|
||||
|
||||
virtual void SetAt(unsigned int index, Object^ value);
|
||||
|
||||
virtual event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ VectorChanged
|
||||
{
|
||||
virtual Windows::Foundation::EventRegistrationToken add(Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ e)
|
||||
{
|
||||
return TreeNodeChanged += e;
|
||||
}
|
||||
|
||||
virtual void remove(Windows::Foundation::EventRegistrationToken t)
|
||||
{
|
||||
TreeNodeChanged -= t;
|
||||
}
|
||||
|
||||
internal: virtual void raise(Windows::UI::Xaml::Interop::IBindableObservableVector^ vector, Platform::Object^ e)
|
||||
{
|
||||
TreeNodeChanged(vector, e);
|
||||
}
|
||||
}
|
||||
|
||||
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;
|
||||
|
||||
virtual property unsigned int Size
|
||||
{
|
||||
unsigned int get();
|
||||
}
|
||||
|
||||
property Object^ Data
|
||||
{
|
||||
Object^ get();
|
||||
void set(Object^ value);
|
||||
}
|
||||
|
||||
property TreeNode^ ParentNode
|
||||
{
|
||||
TreeNode^ get();
|
||||
void set(TreeNode^ value);
|
||||
}
|
||||
|
||||
property bool IsExpanded
|
||||
{
|
||||
bool get();
|
||||
void set(bool value);
|
||||
}
|
||||
|
||||
property bool HasItems
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
//A lone TreeNode will have a depth of -1, this is to show that it is not appended
|
||||
//under the TreeView's invisible root node. Once added into the TreeView via
|
||||
//that method, the depth of the node will be calculated appropriately.
|
||||
property int Depth
|
||||
{
|
||||
int get();
|
||||
}
|
||||
|
||||
event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ TreeNodeChanged;
|
||||
|
||||
private:
|
||||
TreeNode^ parentNode = nullptr;
|
||||
Object^ data = nullptr;
|
||||
bool isExpanded = false;
|
||||
Platform::Collections::Vector<TreeNode^>^ childrenVector = ref new Platform::Collections::Vector<TreeNode^>();
|
||||
void ChildrenVectorChanged(Windows::Foundation::Collections::IObservableVector<TreeNode^>^ sender, Windows::Foundation::Collections::IVectorChangedEventArgs^ e);
|
||||
};
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "TreeView.h"
|
||||
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
|
||||
namespace TreeViewControl {
|
||||
|
||||
TreeView::TreeView()
|
||||
{
|
||||
flatViewModel = ref new ViewModel;
|
||||
rootNode = ref new TreeNode();
|
||||
|
||||
flatViewModel->ExpandNode(rootNode);
|
||||
|
||||
CanReorderItems = true;
|
||||
AllowDrop = true;
|
||||
CanDragItems = true;
|
||||
|
||||
rootNode->VectorChanged += ref new BindableVectorChangedEventHandler(flatViewModel, &ViewModel::TreeNodeVectorChanged);
|
||||
ItemClick += ref new Windows::UI::Xaml::Controls::ItemClickEventHandler(this, &TreeView::TreeView_OnItemClick);
|
||||
DragItemsStarting += ref new Windows::UI::Xaml::Controls::DragItemsStartingEventHandler(this, &TreeView::TreeView_DragItemsStarting);
|
||||
DragItemsCompleted += ref new Windows::Foundation::TypedEventHandler<Windows::UI::Xaml::Controls::ListViewBase ^, Windows::UI::Xaml::Controls::DragItemsCompletedEventArgs ^>(this, &TreeView::TreeView_DragItemsCompleted);
|
||||
ItemsSource = flatViewModel;
|
||||
}
|
||||
|
||||
void TreeView::TreeView_OnItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ args)
|
||||
{
|
||||
TreeViewItemClickEventArgs^ treeViewArgs = ref new TreeViewItemClickEventArgs();
|
||||
treeViewArgs->ClickedItem = args->ClickedItem;
|
||||
|
||||
TreeViewItemClick(this, treeViewArgs);
|
||||
|
||||
if (!treeViewArgs->IsHandled)
|
||||
{
|
||||
TreeNode^ targetNode = (TreeNode^)args->ClickedItem;
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
flatViewModel->CollapseNode(targetNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
flatViewModel->ExpandNode(targetNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::TreeView_DragItemsStarting(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e)
|
||||
{
|
||||
draggedTreeViewItem = (TreeViewItem^)this->ContainerFromItem(e->Items->GetAt(0));
|
||||
}
|
||||
|
||||
void TreeView::TreeView_DragItemsCompleted(Windows::UI::Xaml::Controls::ListViewBase^ sender, Windows::UI::Xaml::Controls::DragItemsCompletedEventArgs^ args)
|
||||
{
|
||||
draggedTreeViewItem = nullptr;
|
||||
}
|
||||
|
||||
void TreeView::OnDrop(Windows::UI::Xaml::DragEventArgs^ e)
|
||||
{
|
||||
if (e->AcceptedOperation == Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move)
|
||||
{
|
||||
Panel^ panel = this->ItemsPanelRoot;
|
||||
Windows::Foundation::Point point = e->GetPosition(panel);
|
||||
|
||||
int aboveIndex = -1;
|
||||
int belowIndex = -1;
|
||||
unsigned int relativeIndex;
|
||||
|
||||
IInsertionPanel^ insertionPanel = (IInsertionPanel^)panel;
|
||||
|
||||
if (insertionPanel != nullptr)
|
||||
{
|
||||
insertionPanel->GetInsertionIndexes(point, &aboveIndex, &belowIndex);
|
||||
|
||||
TreeNode^ aboveNode = (TreeNode^)flatViewModel->GetAt(aboveIndex);
|
||||
TreeNode^ belowNode = (TreeNode^)flatViewModel->GetAt(belowIndex);
|
||||
TreeNode^ targetNode = (TreeNode^)this->ItemFromContainer(draggedTreeViewItem);
|
||||
|
||||
//Between two items
|
||||
if (aboveNode && belowNode)
|
||||
{
|
||||
targetNode->ParentNode->IndexOf(targetNode, &relativeIndex);
|
||||
targetNode->ParentNode->RemoveAt(relativeIndex);
|
||||
|
||||
if (belowNode->ParentNode == aboveNode)
|
||||
{
|
||||
aboveNode->InsertAt(0, targetNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
aboveNode->ParentNode->IndexOf(aboveNode, &relativeIndex);
|
||||
aboveNode->ParentNode->InsertAt(relativeIndex + 1, targetNode);
|
||||
}
|
||||
}
|
||||
//Bottom of the list
|
||||
else if (aboveNode && !belowNode)
|
||||
{
|
||||
targetNode->ParentNode->IndexOf(targetNode, &relativeIndex);
|
||||
targetNode->ParentNode->RemoveAt(relativeIndex);
|
||||
|
||||
aboveNode->ParentNode->IndexOf(aboveNode, &relativeIndex);
|
||||
aboveNode->ParentNode->InsertAt(relativeIndex + 1, targetNode);
|
||||
}
|
||||
//Top of the list
|
||||
else if (!aboveNode && belowNode)
|
||||
{
|
||||
targetNode->ParentNode->IndexOf(targetNode, &relativeIndex);
|
||||
targetNode->ParentNode->RemoveAt(relativeIndex);
|
||||
|
||||
rootNode->InsertAt(0, targetNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e->Handled = true;
|
||||
ListViewBase::OnDrop(e);
|
||||
}
|
||||
|
||||
void TreeView::OnDragOver(Windows::UI::Xaml::DragEventArgs^ e)
|
||||
{
|
||||
Windows::ApplicationModel::DataTransfer::DataPackageOperation savedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None;
|
||||
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None;
|
||||
|
||||
Panel^ panel = this->ItemsPanelRoot;
|
||||
Windows::Foundation::Point point = e->GetPosition(panel);
|
||||
|
||||
int aboveIndex = -1;
|
||||
int belowIndex = -1;
|
||||
|
||||
IInsertionPanel^ insertionPanel = (IInsertionPanel^)panel;
|
||||
|
||||
if (insertionPanel != nullptr)
|
||||
{
|
||||
insertionPanel->GetInsertionIndexes(point, &aboveIndex, &belowIndex);
|
||||
|
||||
if (aboveIndex > -1)
|
||||
{
|
||||
TreeNode^ aboveNode = (TreeNode^)flatViewModel->GetAt(aboveIndex);
|
||||
TreeNode^ targetNode = (TreeNode^)this->ItemFromContainer(draggedTreeViewItem);
|
||||
|
||||
TreeNode^ ancestorNode = aboveNode;
|
||||
while (ancestorNode != nullptr && ancestorNode != targetNode)
|
||||
{
|
||||
ancestorNode = ancestorNode->ParentNode;
|
||||
}
|
||||
|
||||
if (ancestorNode == nullptr)
|
||||
{
|
||||
savedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move;
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
savedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move;
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move;
|
||||
}
|
||||
}
|
||||
|
||||
ListViewBase::OnDragOver(e);
|
||||
e->AcceptedOperation = savedOperation;
|
||||
}
|
||||
|
||||
void TreeView::ExpandNode(TreeNode^ targetNode)
|
||||
{
|
||||
flatViewModel->ExpandNode(targetNode);
|
||||
}
|
||||
|
||||
void TreeView::CollapseNode(TreeNode^ targetNode)
|
||||
{
|
||||
flatViewModel->CollapseNode(targetNode);
|
||||
}
|
||||
|
||||
void TreeView::PrepareContainerForItemOverride(DependencyObject^ element, Object^ item)
|
||||
{
|
||||
((UIElement^)element)->AllowDrop = true;
|
||||
|
||||
ListView::PrepareContainerForItemOverride(element, item);
|
||||
}
|
||||
|
||||
DependencyObject^ TreeView::GetContainerForItemOverride()
|
||||
{
|
||||
TreeViewItem^ targetItem = ref new TreeViewItem();
|
||||
return (DependencyObject^)targetItem;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#pragma once
|
||||
#include "TreeNode.h"
|
||||
#include "ViewModel.h"
|
||||
#include "TreeViewItem.h"
|
||||
|
||||
namespace TreeViewControl {
|
||||
public ref class TreeViewItemClickEventArgs sealed
|
||||
{
|
||||
public:
|
||||
TreeViewItemClickEventArgs() {}
|
||||
|
||||
property Object^ ClickedItem
|
||||
{
|
||||
Object^ get() { return clickedItem; };
|
||||
void set(Object^ value) { clickedItem = value; };
|
||||
}
|
||||
|
||||
property bool IsHandled
|
||||
{
|
||||
bool get() { return isHandled; };
|
||||
void set(bool value) { isHandled = value; };
|
||||
}
|
||||
private:
|
||||
Object^ clickedItem = nullptr;
|
||||
bool isHandled = false;
|
||||
};
|
||||
|
||||
ref class TreeView;
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
public delegate void TreeViewItemClickHandler(TreeView^ sender, TreeViewItemClickEventArgs^ args);
|
||||
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
public ref class TreeView sealed : Windows::UI::Xaml::Controls::ListView
|
||||
{
|
||||
public:
|
||||
TreeView();
|
||||
|
||||
//This event is used to expose an alternative to itemclick to developers.
|
||||
event TreeViewItemClickHandler^ TreeViewItemClick;
|
||||
|
||||
//This RootNode property is used by the TreeView to handle additions into the TreeView and
|
||||
//accurate VectorChange with multiple 'root level nodes'. This node will not be placed
|
||||
//in the flatViewModel, but has it's vectorchanged event hooked up to flatViewModel's
|
||||
//handler.
|
||||
property TreeNode^ RootNode
|
||||
{
|
||||
TreeNode^ get() { return rootNode; };
|
||||
}
|
||||
|
||||
void TreeView_OnItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ args);
|
||||
|
||||
void TreeView_DragItemsStarting(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e);
|
||||
|
||||
void TreeView_DragItemsCompleted(Windows::UI::Xaml::Controls::ListViewBase^ sender, Windows::UI::Xaml::Controls::DragItemsCompletedEventArgs^ args);
|
||||
|
||||
void ExpandNode(TreeNode^ targetNode);
|
||||
|
||||
void CollapseNode(TreeNode^ targetNode);
|
||||
|
||||
protected:
|
||||
void PrepareContainerForItemOverride(DependencyObject^ element, Object^ item) override;
|
||||
Windows::UI::Xaml::DependencyObject^ GetContainerForItemOverride() override;
|
||||
|
||||
void OnDrop(Windows::UI::Xaml::DragEventArgs^ e) override;
|
||||
void OnDragOver(Windows::UI::Xaml::DragEventArgs^ e) override;
|
||||
|
||||
private:
|
||||
TreeNode^ rootNode;
|
||||
ViewModel^ flatViewModel;
|
||||
|
||||
internal:
|
||||
TreeViewItem^ draggedTreeViewItem;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{bdc228d2-7929-5a98-b7ba-5e28bd1adbcf}</ProjectGuid>
|
||||
<Keyword>WindowsRuntimeComponent</Keyword>
|
||||
<ProjectName>TreeViewControl</ProjectName>
|
||||
<RootNamespace>TreeViewControl</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="IntegerToIndentationConverter.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="TreeNode.h" />
|
||||
<ClInclude Include="TreeView.h" />
|
||||
<ClInclude Include="TreeViewItem.h" />
|
||||
<ClInclude Include="TreeViewItemAutomationPeer.h" />
|
||||
<ClInclude Include="ViewModel.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="IntegerToIndentationConverter.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TreeNode.cpp" />
|
||||
<ClCompile Include="TreeView.cpp" />
|
||||
<ClCompile Include="TreeViewItem.cpp" />
|
||||
<ClCompile Include="TreeViewItemAutomationPeer.cpp" />
|
||||
<ClCompile Include="ViewModel.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resources">
|
||||
<UniqueIdentifier>96c875b2-800f-42e2-aba6-ef897e02ec12</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="TreeNode.cpp" />
|
||||
<ClCompile Include="TreeView.cpp" />
|
||||
<ClCompile Include="TreeViewItem.cpp" />
|
||||
<ClCompile Include="TreeViewItemAutomationPeer.cpp" />
|
||||
<ClCompile Include="ViewModel.cpp" />
|
||||
<ClCompile Include="IntegerToIndentationConverter.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="TreeNode.h" />
|
||||
<ClInclude Include="TreeView.h" />
|
||||
<ClInclude Include="TreeViewItem.h" />
|
||||
<ClInclude Include="TreeViewItemAutomationPeer.h" />
|
||||
<ClInclude Include="ViewModel.h" />
|
||||
<ClInclude Include="IntegerToIndentationConverter.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,127 +0,0 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "TreeViewItem.h"
|
||||
#include "TreeViewItemAutomationPeer.h"
|
||||
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Platform;
|
||||
|
||||
namespace TreeViewControl {
|
||||
TreeViewItem::TreeViewItem()
|
||||
{
|
||||
}
|
||||
|
||||
TreeViewItem::~TreeViewItem()
|
||||
{
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Controls::ListView^ TreeViewItem::GetAncestorListView(TreeViewItem^ targetItem)
|
||||
{
|
||||
DependencyObject^ TreeViewItemAncestor = (DependencyObject^)this;
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = nullptr;
|
||||
while (TreeViewItemAncestor != nullptr && ancestorListView == nullptr)
|
||||
{
|
||||
TreeViewItemAncestor = Windows::UI::Xaml::Media::VisualTreeHelper::GetParent(TreeViewItemAncestor);
|
||||
ancestorListView = dynamic_cast<Windows::UI::Xaml::Controls::ListView^>(TreeViewItemAncestor);
|
||||
}
|
||||
return ancestorListView;
|
||||
}
|
||||
|
||||
void TreeViewItem::OnDrop(Windows::UI::Xaml::DragEventArgs^ e)
|
||||
{
|
||||
if (e->AcceptedOperation == Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move)
|
||||
{
|
||||
TreeViewItem^ droppedOnItem = (TreeViewItem^)this;
|
||||
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetAncestorListView(droppedOnItem);
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
TreeViewItem^ droppedItem = ancestorTreeView->draggedTreeViewItem;
|
||||
TreeNode^ droppedNode = (TreeNode^)ancestorTreeView->ItemFromContainer(droppedItem);
|
||||
TreeNode^ droppedOnNode = (TreeNode^)ancestorTreeView->ItemFromContainer(droppedOnItem);
|
||||
|
||||
//Remove the item that was dragged
|
||||
unsigned int removeIndex;
|
||||
droppedNode->ParentNode->IndexOf(droppedNode, &removeIndex);
|
||||
|
||||
if (droppedNode != droppedOnNode)
|
||||
{
|
||||
droppedNode->ParentNode->RemoveAt(removeIndex);
|
||||
|
||||
//Append the dragged dropped item as a child of the node it was dropped onto
|
||||
droppedOnNode->Append(droppedNode);
|
||||
|
||||
//If not set to true then the Reorder code of listview wil override what is being done here.
|
||||
e->Handled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeViewItem::OnDragEnter(Windows::UI::Xaml::DragEventArgs^ e)
|
||||
{
|
||||
TreeViewItem^ draggedOverItem = (TreeViewItem^)this;
|
||||
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None;
|
||||
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetAncestorListView(draggedOverItem);
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
TreeViewItem^ draggedTreeViewItem = ancestorTreeView->draggedTreeViewItem;
|
||||
TreeNode^ draggedNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedTreeViewItem);
|
||||
TreeNode^ draggedOverNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedOverItem);
|
||||
TreeNode^ walkNode = draggedOverNode->ParentNode;
|
||||
|
||||
while (walkNode != nullptr && walkNode != draggedNode)
|
||||
{
|
||||
walkNode = walkNode->ParentNode;
|
||||
}
|
||||
|
||||
if (walkNode != draggedNode && draggedNode != draggedOverNode)
|
||||
{
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeViewItem::OnDragOver(Windows::UI::Xaml::DragEventArgs^ e)
|
||||
{
|
||||
e->DragUIOverride->IsGlyphVisible = true;
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None;
|
||||
|
||||
TreeViewItem^ draggedOverItem = (TreeViewItem^)this;
|
||||
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetAncestorListView(draggedOverItem);
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
TreeViewItem^ draggedTreeViewItem = ancestorTreeView->draggedTreeViewItem;
|
||||
TreeNode^ draggedNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedTreeViewItem);
|
||||
TreeNode^ draggedOverNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedOverItem);
|
||||
TreeNode^ walkNode = draggedOverNode->ParentNode;
|
||||
|
||||
while (walkNode != nullptr && walkNode != draggedNode)
|
||||
{
|
||||
walkNode = walkNode->ParentNode;
|
||||
}
|
||||
|
||||
if (walkNode != draggedNode && draggedNode != draggedOverNode)
|
||||
{
|
||||
e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Automation::Peers::AutomationPeer^ TreeViewItem::OnCreateAutomationPeer()
|
||||
{
|
||||
return ref new TreeViewItemAutomationPeer(this);
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace TreeViewControl {
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class TreeViewItem sealed : Windows::UI::Xaml::Controls::ListViewItem
|
||||
{
|
||||
public:
|
||||
TreeViewItem();
|
||||
|
||||
virtual ~TreeViewItem();
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Controls::ListView^ GetAncestorListView(TreeViewItem^ targetItem);
|
||||
|
||||
protected:
|
||||
void OnDrop(Windows::UI::Xaml::DragEventArgs^ e) override;
|
||||
void OnDragEnter(Windows::UI::Xaml::DragEventArgs^ e) override;
|
||||
void OnDragOver(Windows::UI::Xaml::DragEventArgs^ e) override;
|
||||
Windows::UI::Xaml::Automation::Peers::AutomationPeer^ OnCreateAutomationPeer() override;
|
||||
};
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "TreeViewItemAutomationPeer.h"
|
||||
#include "TreeNode.h"
|
||||
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Automation;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
|
||||
|
||||
namespace TreeViewControl {
|
||||
//IExpandCollapseProvider
|
||||
Windows::UI::Xaml::Automation::ExpandCollapseState TreeViewItemAutomationPeer::ExpandCollapseState::get()
|
||||
{
|
||||
Windows::UI::Xaml::Automation::ExpandCollapseState currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed;
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner);
|
||||
|
||||
TreeNode^ targetNode;
|
||||
TreeNode^ targetParentNode;
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner);
|
||||
|
||||
if (Owner->AllowDrop)
|
||||
{
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::LeafNode;
|
||||
}
|
||||
}
|
||||
|
||||
return currentState;
|
||||
}
|
||||
|
||||
void TreeViewItemAutomationPeer::Collapse()
|
||||
{
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner);
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
TreeNode^ targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner);
|
||||
ancestorTreeView->CollapseNode(targetNode);
|
||||
RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeViewItemAutomationPeer::Expand()
|
||||
{
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner);
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
TreeNode^ targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner);
|
||||
ancestorTreeView->ExpandNode(targetNode);
|
||||
RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeViewItemAutomationPeer::RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState newState)
|
||||
{
|
||||
Windows::UI::Xaml::Automation::ExpandCollapseState oldState;
|
||||
|
||||
if (newState == Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded)
|
||||
{
|
||||
oldState = Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldState = Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded;
|
||||
}
|
||||
|
||||
RaisePropertyChangedEvent(ExpandCollapsePatternIdentifiers::ExpandCollapseStateProperty, oldState, newState);
|
||||
}
|
||||
|
||||
//Position override
|
||||
|
||||
//These methods are being overridden so that the TreeView under narrator reads out
|
||||
//the position of an item as compared to it's children, not it's overall position
|
||||
//in the listview. I've included an override for level as well, to give context on
|
||||
//how deep in the tree an item is.
|
||||
int TreeViewItemAutomationPeer::GetSizeOfSetCore()
|
||||
{
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner);
|
||||
|
||||
TreeNode^ targetNode;
|
||||
TreeNode^ targetParentNode;
|
||||
|
||||
int setSize = 0;
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner);
|
||||
targetParentNode = targetNode->ParentNode;
|
||||
setSize = targetParentNode->Size;
|
||||
}
|
||||
|
||||
return setSize;
|
||||
}
|
||||
|
||||
int TreeViewItemAutomationPeer::GetPositionInSetCore()
|
||||
{
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner);
|
||||
|
||||
TreeNode^ targetNode;
|
||||
TreeNode^ targetParentNode;
|
||||
|
||||
int positionInSet = 0;
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner);
|
||||
unsigned int positionInt;
|
||||
targetParentNode = targetNode->ParentNode;
|
||||
targetParentNode->IndexOf(targetNode, &positionInt);
|
||||
positionInSet = (int)positionInt + 1;
|
||||
}
|
||||
|
||||
return positionInSet;
|
||||
}
|
||||
|
||||
int TreeViewItemAutomationPeer::GetLevelCore()
|
||||
{
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner);
|
||||
|
||||
TreeNode^ targetNode;
|
||||
TreeNode^ targetParentNode;
|
||||
|
||||
int levelValue = 0;
|
||||
|
||||
if (ancestorListView)
|
||||
{
|
||||
TreeView^ ancestorTreeView = (TreeView^)ancestorListView;
|
||||
targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner);
|
||||
levelValue = targetNode->Depth + 1;
|
||||
}
|
||||
|
||||
return levelValue;
|
||||
}
|
||||
|
||||
Platform::Object^ TreeViewItemAutomationPeer::GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface)
|
||||
{
|
||||
if (patternInterface == Windows::UI::Xaml::Automation::Peers::PatternInterface::ExpandCollapse)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return ListViewItemAutomationPeer::GetPatternCore(patternInterface);
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Controls::ListView^ TreeViewItemAutomationPeer::GetParentListView(DependencyObject^ Owner)
|
||||
{
|
||||
DependencyObject^ treeViewItemAncestor = Owner;
|
||||
Windows::UI::Xaml::Controls::ListView^ ancestorListView = nullptr;
|
||||
while (treeViewItemAncestor != nullptr && ancestorListView == nullptr)
|
||||
{
|
||||
treeViewItemAncestor = Windows::UI::Xaml::Media::VisualTreeHelper::GetParent(treeViewItemAncestor);
|
||||
ancestorListView = dynamic_cast<Windows::UI::Xaml::Controls::ListView^>(treeViewItemAncestor);
|
||||
}
|
||||
|
||||
return ancestorListView;
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
#include "TreeViewItem.h"
|
||||
#include "TreeView.h"
|
||||
|
||||
namespace TreeViewControl {
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
public ref class TreeViewItemAutomationPeer : Windows::UI::Xaml::Automation::Peers::ListViewItemAutomationPeer, Windows::UI::Xaml::Automation::Provider::IExpandCollapseProvider
|
||||
{
|
||||
internal:
|
||||
TreeViewItemAutomationPeer(TreeViewItem^ owner) :Windows::UI::Xaml::Automation::Peers::ListViewItemAutomationPeer(owner) {};
|
||||
|
||||
public:
|
||||
//IExpandCollapseProvider
|
||||
virtual void Collapse();
|
||||
|
||||
virtual void Expand();
|
||||
|
||||
property Windows::UI::Xaml::Automation::ExpandCollapseState ExpandCollapseState
|
||||
{
|
||||
virtual Windows::UI::Xaml::Automation::ExpandCollapseState get();
|
||||
}
|
||||
|
||||
void RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState newState);
|
||||
|
||||
//Position override
|
||||
int GetSizeOfSetCore() override;
|
||||
|
||||
int GetPositionInSetCore() override;
|
||||
|
||||
int GetLevelCore() override;
|
||||
|
||||
protected:
|
||||
Platform::Object^ GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface) override;
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Controls::ListView^ GetParentListView(DependencyObject^ Owner);
|
||||
};
|
||||
}
|
||||
|
|
@ -1,450 +0,0 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "ViewModel.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::UI::Xaml::Interop;
|
||||
using namespace Windows::UI::Xaml::Data;
|
||||
|
||||
namespace TreeViewControl {
|
||||
ViewModel::ViewModel()
|
||||
{
|
||||
flatVectorRealizedItems->VectorChanged += ref new VectorChangedEventHandler<TreeNode ^>(this, &ViewModel::UpdateTreeView);
|
||||
}
|
||||
|
||||
void ViewModel::Append(Object^ value)
|
||||
{
|
||||
TreeNode^ targetNode = (TreeNode^)value;
|
||||
flatVectorRealizedItems->Append(targetNode);
|
||||
|
||||
collectionChangedEventTokenVector.push_back(targetNode->VectorChanged += ref new BindableVectorChangedEventHandler(this, &ViewModel::TreeNodeVectorChanged));
|
||||
propertyChangedEventTokenVector.push_back(targetNode->PropertyChanged += ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &ViewModel::TreeNodePropertyChanged));
|
||||
}
|
||||
|
||||
void ViewModel::Clear()
|
||||
{
|
||||
|
||||
while (flatVectorRealizedItems->Size != 0)
|
||||
{
|
||||
RemoveAtEnd();
|
||||
}
|
||||
}
|
||||
|
||||
IBindableIterator^ ViewModel::First()
|
||||
{
|
||||
return dynamic_cast<IBindableIterator^>(flatVectorRealizedItems->First());
|
||||
}
|
||||
|
||||
Object^ ViewModel::GetAt(unsigned int index)
|
||||
{
|
||||
if ((int)index > -1 && (int)index < flatVectorRealizedItems->Size)
|
||||
{
|
||||
return flatVectorRealizedItems->GetAt(index);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IBindableVectorView^ ViewModel::GetView()
|
||||
{
|
||||
return safe_cast<IBindableVectorView^>(flatVectorRealizedItems->GetView());
|
||||
}
|
||||
|
||||
bool ViewModel::IndexOf(Object^ value, unsigned int* index)
|
||||
{
|
||||
return flatVectorRealizedItems->IndexOf((TreeNode^)value, index);
|
||||
}
|
||||
|
||||
void ViewModel::InsertAt(unsigned int index, Object^ value)
|
||||
{
|
||||
if ((int)index > -1 && (int)index <= flatVectorRealizedItems->Size)
|
||||
{
|
||||
TreeNode^ targetNode = (TreeNode^)value;
|
||||
flatVectorRealizedItems->InsertAt(index, targetNode);
|
||||
|
||||
auto eventIndex = collectionChangedEventTokenVector.begin() + index;
|
||||
collectionChangedEventTokenVector.insert(eventIndex, targetNode->VectorChanged += ref new BindableVectorChangedEventHandler(this, &ViewModel::TreeNodeVectorChanged));
|
||||
|
||||
eventIndex = propertyChangedEventTokenVector.begin() + index;
|
||||
propertyChangedEventTokenVector.insert(eventIndex,targetNode->PropertyChanged += ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &ViewModel::TreeNodePropertyChanged));
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::RemoveAt(unsigned int index)
|
||||
{
|
||||
if ((int)index > -1 && (int)index < flatVectorRealizedItems->Size)
|
||||
{
|
||||
TreeNode^ targetNode = flatVectorRealizedItems->GetAt(index);
|
||||
flatVectorRealizedItems->RemoveAt(index);
|
||||
|
||||
auto eventIndex = collectionChangedEventTokenVector.begin() + index;
|
||||
targetNode->VectorChanged -= collectionChangedEventTokenVector[index];
|
||||
collectionChangedEventTokenVector.erase(eventIndex);
|
||||
|
||||
eventIndex = propertyChangedEventTokenVector.begin() + index;
|
||||
targetNode->PropertyChanged -= propertyChangedEventTokenVector[index];
|
||||
propertyChangedEventTokenVector.erase(eventIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::RemoveAtEnd()
|
||||
{
|
||||
int index = flatVectorRealizedItems->Size - 1;
|
||||
if (index >= 0)
|
||||
{
|
||||
TreeNode^ targetNode = flatVectorRealizedItems->GetAt(index);
|
||||
flatVectorRealizedItems->RemoveAt(index);
|
||||
|
||||
auto eventIndex = collectionChangedEventTokenVector.begin() + index;
|
||||
targetNode->VectorChanged -= collectionChangedEventTokenVector[index];
|
||||
collectionChangedEventTokenVector.erase(eventIndex);
|
||||
|
||||
eventIndex = propertyChangedEventTokenVector.begin() + index;
|
||||
targetNode->PropertyChanged -= propertyChangedEventTokenVector[index];
|
||||
propertyChangedEventTokenVector.erase(eventIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::SetAt(unsigned int index, Object^ value)
|
||||
{
|
||||
if ((int)index > -1 && (int)index < flatVectorRealizedItems->Size)
|
||||
{
|
||||
TreeNode^ targetNode = (TreeNode^)value;
|
||||
TreeNode^ removeNode = flatVectorRealizedItems->GetAt(index);
|
||||
flatVectorRealizedItems->SetAt(index, targetNode);
|
||||
|
||||
auto eventIndex = collectionChangedEventTokenVector.begin() + index;
|
||||
removeNode->VectorChanged -= collectionChangedEventTokenVector[index];
|
||||
collectionChangedEventTokenVector.erase(eventIndex);
|
||||
collectionChangedEventTokenVector.insert(eventIndex, targetNode->VectorChanged += ref new BindableVectorChangedEventHandler(this, &ViewModel::TreeNodeVectorChanged));
|
||||
|
||||
eventIndex = propertyChangedEventTokenVector.begin() + index;
|
||||
targetNode->PropertyChanged -= propertyChangedEventTokenVector[index];
|
||||
propertyChangedEventTokenVector.erase(eventIndex);
|
||||
propertyChangedEventTokenVector.insert(eventIndex, targetNode->PropertyChanged += ref new Windows::UI::Xaml::Data::PropertyChangedEventHandler(this, &ViewModel::TreeNodePropertyChanged));
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::ExpandNode(TreeNode^ targetNode)
|
||||
{
|
||||
if (!targetNode->IsExpanded)
|
||||
{
|
||||
targetNode->IsExpanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::CollapseNode(TreeNode^ targetNode)
|
||||
{
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
targetNode->IsExpanded = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::AddNodeToView(TreeNode^ targetNode, int index)
|
||||
{
|
||||
InsertAt(index, targetNode);
|
||||
}
|
||||
|
||||
int ViewModel::AddNodeDescendantsToView(TreeNode^ targetNode, int index, int offset)
|
||||
{
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
TreeNode^ childNode;
|
||||
for (int i = 0; i < (int)targetNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)targetNode->GetAt(i);
|
||||
offset++;
|
||||
AddNodeToView(childNode, index + offset);
|
||||
offset = AddNodeDescendantsToView(childNode, index, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void ViewModel::RemoveNodeAndDescendantsFromView(TreeNode^ targetNode)
|
||||
{
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
TreeNode^ childNode;
|
||||
for (int i = 0; i < (int)targetNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)targetNode->GetAt(i);
|
||||
RemoveNodeAndDescendantsFromView(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
int index = IndexOf(targetNode);
|
||||
RemoveAt(index);
|
||||
}
|
||||
|
||||
int ViewModel::CountDescendants(TreeNode^ targetNode)
|
||||
{
|
||||
int descendantCount = 0;
|
||||
TreeNode^ childNode;
|
||||
for (int i = 0; i < (int)targetNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)targetNode->GetAt(i);
|
||||
descendantCount++;
|
||||
if (childNode->IsExpanded)
|
||||
{
|
||||
descendantCount = descendantCount + CountDescendants(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
return descendantCount;
|
||||
}
|
||||
|
||||
int ViewModel::IndexOf(TreeNode^ targetNode)
|
||||
{
|
||||
unsigned int index;
|
||||
bool isIndexed = IndexOf(targetNode, &index);
|
||||
if (isIndexed)
|
||||
{
|
||||
return (int)index;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::UpdateTreeView(IObservableVector<TreeNode^>^ sender, IVectorChangedEventArgs^ e)
|
||||
{
|
||||
VectorChanged(this, e);
|
||||
}
|
||||
|
||||
void ViewModel::TreeNodeVectorChanged(IBindableObservableVector^ sender, Platform::Object^ e)
|
||||
{
|
||||
CollectionChange CC = ((IVectorChangedEventArgs^)e)->CollectionChange;
|
||||
switch (CC)
|
||||
{
|
||||
//Reset case, commonly seen when a TreeNode is cleared.
|
||||
//removes all nodes that need removing then
|
||||
//toggles a collapse / expand to ensure order.
|
||||
case (CollectionChange::Reset) :
|
||||
{
|
||||
TreeNode^ resetNode = (TreeNode^)sender;
|
||||
int resetIndex = IndexOf(resetNode);
|
||||
if (resetIndex != Size - 1 && resetNode->IsExpanded)
|
||||
{
|
||||
TreeNode^ childNode = resetNode;
|
||||
TreeNode^ parentNode = resetNode->ParentNode;
|
||||
int stopIndex;
|
||||
bool isLastRelativeChild = true;
|
||||
while (parentNode != nullptr && isLastRelativeChild)
|
||||
{
|
||||
unsigned int relativeIndex;
|
||||
parentNode->IndexOf(childNode, &relativeIndex);
|
||||
if (parentNode->Size - 1 != relativeIndex)
|
||||
{
|
||||
isLastRelativeChild = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
childNode = parentNode;
|
||||
parentNode = parentNode->ParentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (parentNode != nullptr)
|
||||
{
|
||||
unsigned int siblingIndex;
|
||||
parentNode->IndexOf(childNode, &siblingIndex);
|
||||
TreeNode^ siblingNode = (TreeNode^)parentNode->GetAt(siblingIndex + 1);
|
||||
stopIndex = IndexOf(siblingNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
stopIndex = Size;
|
||||
}
|
||||
|
||||
for (int i = stopIndex - 1; i > resetIndex; i--)
|
||||
{
|
||||
if ((flatVectorRealizedItems->GetAt(i))->ParentNode == nullptr)
|
||||
{
|
||||
RemoveNodeAndDescendantsFromView(flatVectorRealizedItems->GetAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (resetNode->IsExpanded)
|
||||
{
|
||||
CollapseNode(resetNode);
|
||||
ExpandNode(resetNode);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//Inserts the TreeNode into the correct index of the ViewModel
|
||||
case (CollectionChange::ItemInserted) :
|
||||
{
|
||||
//We will find the correct index of insertion by first checking if the
|
||||
//node we are inserting into is expanded. If it is we will start walking
|
||||
//down the tree and counting the open items. This is to ensure we place
|
||||
//the inserted item in the correct index. If along the way we bump into
|
||||
//the item being inserted, we insert there then return, because we don't
|
||||
//need to do anything further.
|
||||
unsigned int index = ((IVectorChangedEventArgs^)e)->Index;
|
||||
TreeNode^ targetNode = (TreeNode^)sender->GetAt(index);
|
||||
TreeNode^ parentNode = targetNode->ParentNode;
|
||||
TreeNode^ childNode;
|
||||
int parentIndex = IndexOf(parentNode);
|
||||
int allOpenedDescendantsCount = 0;
|
||||
if (parentNode->IsExpanded)
|
||||
{
|
||||
for (int i = 0; i < (int)parentNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)parentNode->GetAt(i);
|
||||
if (childNode == targetNode)
|
||||
{
|
||||
AddNodeToView(targetNode, (parentIndex + i + 1 + allOpenedDescendantsCount));
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
AddNodeDescendantsToView(targetNode, parentIndex + i + 1, allOpenedDescendantsCount);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (childNode->IsExpanded)
|
||||
{
|
||||
allOpenedDescendantsCount += CountDescendants(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
AddNodeToView(targetNode, (parentIndex + parentNode->Size + allOpenedDescendantsCount));
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
AddNodeDescendantsToView(targetNode, parentIndex + parentNode->Size, allOpenedDescendantsCount);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//Removes a node from the ViewModel when a TreeNode
|
||||
//removes a child.
|
||||
case (CollectionChange::ItemRemoved) :
|
||||
{
|
||||
TreeNode^ removeNode = (TreeNode^)sender;
|
||||
int removeIndex = IndexOf(removeNode);
|
||||
|
||||
if (removeIndex != Size - 1 && removeNode->IsExpanded)
|
||||
{
|
||||
TreeNode^ childNode = removeNode;
|
||||
TreeNode^ parentNode = removeNode->ParentNode;
|
||||
int stopIndex;
|
||||
bool isLastRelativeChild = true;
|
||||
while (parentNode != nullptr && isLastRelativeChild)
|
||||
{
|
||||
unsigned int relativeIndex;
|
||||
parentNode->IndexOf(childNode, &relativeIndex);
|
||||
if (parentNode->Size - 1 != relativeIndex)
|
||||
{
|
||||
isLastRelativeChild = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
childNode = parentNode;
|
||||
parentNode = parentNode->ParentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (parentNode != nullptr)
|
||||
{
|
||||
unsigned int siblingIndex;
|
||||
parentNode->IndexOf(childNode, &siblingIndex);
|
||||
TreeNode^ siblingNode = (TreeNode^)parentNode->GetAt(siblingIndex + 1);
|
||||
stopIndex = IndexOf(siblingNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
stopIndex = Size;
|
||||
}
|
||||
|
||||
for (int i = stopIndex - 1; i > removeIndex; i--)
|
||||
{
|
||||
if ((flatVectorRealizedItems->GetAt(i))->ParentNode == nullptr)
|
||||
{
|
||||
RemoveNodeAndDescendantsFromView(flatVectorRealizedItems->GetAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//Triggered by a replace such as SetAt.
|
||||
//Updates the TreeNode that changed in the ViewModel.
|
||||
case (CollectionChange::ItemChanged) :
|
||||
{
|
||||
unsigned int index = ((IVectorChangedEventArgs^)e)->Index;
|
||||
TreeNode^ targetNode = (TreeNode^)sender->GetAt(index);
|
||||
TreeNode^ parentNode = targetNode->ParentNode;
|
||||
TreeNode^ childNode;
|
||||
int allOpenedDescendantsCount = 0;
|
||||
int parentIndex = IndexOf(parentNode);
|
||||
|
||||
for (int i = 0; i < (int)parentNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)parentNode->GetAt(i);
|
||||
if (childNode->IsExpanded)
|
||||
{
|
||||
allOpenedDescendantsCount += CountDescendants(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
TreeNode^ removeNode = (TreeNode^)GetAt(parentIndex + index + allOpenedDescendantsCount + 1);
|
||||
if (removeNode->IsExpanded)
|
||||
{
|
||||
CollapseNode(removeNode);
|
||||
}
|
||||
|
||||
RemoveAt(parentIndex + index + allOpenedDescendantsCount + 1);
|
||||
InsertAt(parentIndex + index + allOpenedDescendantsCount + 1, targetNode);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ViewModel::TreeNodePropertyChanged(Object^ sender, PropertyChangedEventArgs^ e)
|
||||
{
|
||||
if (e->PropertyName == "IsExpanded")
|
||||
{
|
||||
TreeNode^ targetNode = (TreeNode^)sender;
|
||||
if (targetNode->IsExpanded)
|
||||
{
|
||||
if (targetNode->Size != 0)
|
||||
{
|
||||
int openedDescendantOffset = 0;
|
||||
int index = IndexOf(targetNode);
|
||||
index = index + 1;
|
||||
TreeNode^ childNode;
|
||||
for (int i = 0; i < (int)targetNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)targetNode->GetAt(i);
|
||||
AddNodeToView(childNode, ((int)index + i + openedDescendantOffset));
|
||||
openedDescendantOffset = AddNodeDescendantsToView(childNode, (index + i), openedDescendantOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeNode^ childNode;
|
||||
for (int i = 0; i < (int)targetNode->Size; i++)
|
||||
{
|
||||
childNode = (TreeNode^)targetNode->GetAt(i);
|
||||
RemoveNodeAndDescendantsFromView(childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
#pragma once
|
||||
#include "TreeNode.h"
|
||||
|
||||
namespace TreeViewControl {
|
||||
/// <summary>
|
||||
/// The ViewModel is responsible for flattening the heirarchical data into a flat list.
|
||||
/// It also tracks changes to the underlying data and updates the flat list accordingly.
|
||||
/// </summary>
|
||||
[Windows::Foundation::Metadata::WebHostHidden]
|
||||
ref class ViewModel sealed : Windows::UI::Xaml::Interop::IBindableObservableVector
|
||||
{
|
||||
internal:
|
||||
ViewModel();
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Add root to the view model. In other cases the app should not
|
||||
/// use this api.
|
||||
/// </summary>
|
||||
virtual void Append(Object^ value);
|
||||
|
||||
virtual void Clear();
|
||||
|
||||
virtual Windows::UI::Xaml::Interop::IBindableIterator^ First();
|
||||
|
||||
virtual Object^ GetAt(unsigned int index);
|
||||
|
||||
virtual Windows::UI::Xaml::Interop::IBindableVectorView^ GetView();
|
||||
|
||||
virtual bool IndexOf(Object^ value, unsigned int* index);
|
||||
|
||||
virtual void InsertAt(unsigned int index, Object^ value);
|
||||
|
||||
virtual void RemoveAt(unsigned int index);
|
||||
|
||||
virtual void RemoveAtEnd();
|
||||
|
||||
virtual void SetAt(unsigned int index, Object^ value);
|
||||
|
||||
virtual property unsigned int Size
|
||||
{
|
||||
unsigned int get() { return flatVectorRealizedItems->Size; };
|
||||
};
|
||||
|
||||
virtual event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ VectorChanged
|
||||
{
|
||||
virtual Windows::Foundation::EventRegistrationToken add(Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ args)
|
||||
{
|
||||
return ViewModelChanged += args;
|
||||
}
|
||||
|
||||
virtual void remove(Windows::Foundation::EventRegistrationToken token)
|
||||
{
|
||||
return ViewModelChanged -= token;
|
||||
}
|
||||
|
||||
virtual void raise(Windows::UI::Xaml::Interop::IBindableObservableVector^ vector, Platform::Object^ e)
|
||||
{
|
||||
ViewModelChanged(vector, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ExpandNode adds the children and all open descendants of the targetNode
|
||||
/// to the ViewModel in their correct flattened index.
|
||||
/// </summary>
|
||||
void ExpandNode(TreeNode^ targetNode);
|
||||
|
||||
/// <summary>
|
||||
/// Collapse node removes all the descendants of the targetNode from the ViewModel.
|
||||
/// </summary>
|
||||
void CollapseNode(TreeNode^ targetNode);
|
||||
|
||||
/// <summary>
|
||||
/// This is the collection changed handler for individual TreeNodes. The collection changes
|
||||
/// from the hierarchical TreeNodes need to be flattened so that we can keep our current
|
||||
/// flat list in sync.
|
||||
/// </summary>
|
||||
/// <param name="sender">TreeNode that has already been changed</param>
|
||||
void TreeNodeVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector^ sender, Platform::Object^ e);
|
||||
|
||||
void TreeNodePropertyChanged(Object^ sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs^ e);
|
||||
|
||||
private:
|
||||
event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ ViewModelChanged;
|
||||
|
||||
Platform::Collections::Vector<TreeNode^>^ flatVectorRealizedItems = ref new Platform::Collections::Vector<TreeNode^>();
|
||||
|
||||
std::vector<Windows::Foundation::EventRegistrationToken> collectionChangedEventTokenVector;
|
||||
|
||||
std::vector<Windows::Foundation::EventRegistrationToken> propertyChangedEventTokenVector;
|
||||
|
||||
void AddNodeToView(TreeNode^ targetNode, int index);
|
||||
|
||||
int AddNodeDescendantsToView(TreeNode^ targetNode, int start, int offset);
|
||||
|
||||
void RemoveNodeAndDescendantsFromView(TreeNode^ targetNode);
|
||||
|
||||
int CountDescendants(TreeNode^ targetNode);
|
||||
|
||||
int IndexOf(TreeNode^ targetNode);
|
||||
|
||||
void UpdateTreeView(Windows::Foundation::Collections::IObservableVector<TreeNode^>^ sender, Windows::Foundation::Collections::IVectorChangedEventArgs^ e);
|
||||
};
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
#include "pch.h"
|
|
@ -1,10 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <collection.h>
|
||||
#include <ppltasks.h>
|
||||
#include <TreeNode.h>
|
||||
#include <ViewModel.h>
|
||||
#include <TreeViewItem.h>
|
||||
#include <TreeView.h>
|
||||
#include <TreeViewItemAutomationPeer.h>
|
||||
#include <IntegerToIndentationConverter.h>
|
|
@ -414,9 +414,6 @@
|
|||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Control\TreeViewControl.vcxproj">
|
||||
<Project>{bdc228d2-7929-5a98-b7ba-5e28bd1adbcf}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WinRTGLTFParser\WinRTGLTFParser.vcxproj">
|
||||
<Project>{31117527-af30-485c-a312-846bc6a25e0b}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -13,8 +13,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SharedGLTFParser", "SharedG
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModelViewer", "ModelViewer\ModelViewer.vcxproj", "{28B2A92C-D6ED-4A02-9448-B554BF5A95DC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TreeViewControl", "Control\TreeViewControl.vcxproj", "{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
SharedGLTFParser\SharedGLTFParser.vcxitems*{31117527-af30-485c-a312-846bc6a25e0b}*SharedItemsImports = 4
|
||||
|
@ -80,18 +78,6 @@ Global
|
|||
{28B2A92C-D6ED-4A02-9448-B554BF5A95DC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{28B2A92C-D6ED-4A02-9448-B554BF5A95DC}.Release|x86.Build.0 = Release|Win32
|
||||
{28B2A92C-D6ED-4A02-9448-B554BF5A95DC}.Release|x86.Deploy.0 = Release|Win32
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Debug|x64.Build.0 = Debug|x64
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Debug|x86.Build.0 = Debug|Win32
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Release|ARM.Build.0 = Release|ARM
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Release|x64.ActiveCfg = Release|x64
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Release|x64.Build.0 = Release|x64
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Release|x86.ActiveCfg = Release|Win32
|
||||
{BDC228D2-7929-5A98-B7BA-5E28BD1ADBCF}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Загрузка…
Ссылка в новой задаче