Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3958 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
32 changed files with 3086 additions and 240 deletions
@ -0,0 +1,8 @@ |
|||||||
|
<Application x:Class="ICSharpCode.TreeView.Demo.App" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
StartupUri="Window1.xaml"> |
||||||
|
<Application.Resources> |
||||||
|
|
||||||
|
</Application.Resources> |
||||||
|
</Application> |
@ -0,0 +1,16 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Configuration; |
||||||
|
using System.Data; |
||||||
|
using System.Linq; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView.Demo |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.IO; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView.Demo |
||||||
|
{ |
||||||
|
public class FileNode : FileSystemNode |
||||||
|
{ |
||||||
|
public FileNode(string path) |
||||||
|
{ |
||||||
|
this.name = Path.GetFileName(path); |
||||||
|
this.info = new FileInfo(path); |
||||||
|
} |
||||||
|
|
||||||
|
FileInfo info; |
||||||
|
string name; |
||||||
|
|
||||||
|
public override object Text |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override object Icon |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return Window1.LoadIcon("File.png"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override object ToolTip |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return info.FullName; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsEditable |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override string LoadEditText() |
||||||
|
{ |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool SaveEditText(string value) |
||||||
|
{ |
||||||
|
if (value.Contains("?")) { |
||||||
|
MessageBox.Show("?"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
else { |
||||||
|
name = value; |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override long? FileSize |
||||||
|
{ |
||||||
|
get { return info.Length; } |
||||||
|
} |
||||||
|
|
||||||
|
public override DateTime? FileModified |
||||||
|
{ |
||||||
|
get { return info.LastWriteTime; } |
||||||
|
} |
||||||
|
|
||||||
|
public override string FullPath |
||||||
|
{ |
||||||
|
get { return info.FullName; } |
||||||
|
} |
||||||
|
|
||||||
|
public override void Paste(IDataObject data) |
||||||
|
{ |
||||||
|
Parent.Paste(data); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Input; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView.Demo |
||||||
|
{ |
||||||
|
public abstract class FileSystemNode : SharpTreeNode |
||||||
|
{ |
||||||
|
public abstract string FullPath { get; } |
||||||
|
|
||||||
|
public virtual long? FileSize |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
public virtual DateTime? FileModified |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() |
||||||
|
{ |
||||||
|
return FullPath; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanCopy(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override IDataObject Copy(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
var data = new DataObject(); |
||||||
|
var paths = SharpTreeNode.ActiveNodes.Cast<FileSystemNode>().Select(n => n.FullPath).ToArray(); |
||||||
|
data.SetData(typeof(string[]), paths); |
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanPaste(IDataObject data) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanDelete(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return nodes.All(n => n.Parent != null); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Delete(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
if (MessageBox.Show("Sure?", "Delete", MessageBoxButton.OKCancel) == MessageBoxResult.OK) { |
||||||
|
DeleteCore(nodes); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override void DeleteCore(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
foreach (var node in nodes.ToArray()) { |
||||||
|
node.Parent.Children.Remove(node); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanDrag(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
ContextMenu menu; |
||||||
|
|
||||||
|
public override ContextMenu GetContextMenu() |
||||||
|
{ |
||||||
|
if (menu == null) { |
||||||
|
menu = new ContextMenu(); |
||||||
|
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Cut }); |
||||||
|
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Copy }); |
||||||
|
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Paste }); |
||||||
|
menu.Items.Add(new Separator()); |
||||||
|
menu.Items.Add(new MenuItem() { Command = ApplicationCommands.Delete }); |
||||||
|
} |
||||||
|
return menu; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.IO; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView.Demo |
||||||
|
{ |
||||||
|
public class FolderNode : FileSystemNode |
||||||
|
{ |
||||||
|
public FolderNode(string path) |
||||||
|
{ |
||||||
|
this.path = path; |
||||||
|
LazyLoading = true; |
||||||
|
} |
||||||
|
|
||||||
|
string path; |
||||||
|
|
||||||
|
public override object Text |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
var name = Path.GetFileName(path); |
||||||
|
if (name == "") return path; |
||||||
|
return name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override object Icon |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return Window1.LoadIcon("Folder.png"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override object ExpandedIcon |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return Window1.LoadIcon("FolderOpened.png"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsCheckable |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override string FullPath |
||||||
|
{ |
||||||
|
get { return path; } |
||||||
|
} |
||||||
|
|
||||||
|
public override void LoadChildren() |
||||||
|
{ |
||||||
|
try { |
||||||
|
foreach (var p in Directory.GetDirectories(path) |
||||||
|
.OrderBy(d => Path.GetDirectoryName(d))) { |
||||||
|
Children.Add(new FolderNode(p)); |
||||||
|
} |
||||||
|
foreach (var p in Directory.GetFiles(path) |
||||||
|
.OrderBy(f => Path.GetFileName(f))) { |
||||||
|
Children.Add(new FileNode(p)); |
||||||
|
} |
||||||
|
} |
||||||
|
catch { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override DropEffect CanDrop(IDataObject data, DropEffect requestedEffect) |
||||||
|
{ |
||||||
|
var paths = data.GetData(typeof(string[])) as string[]; |
||||||
|
if (paths != null) { |
||||||
|
return requestedEffect == DropEffect.Link ? DropEffect.Move : requestedEffect; |
||||||
|
} |
||||||
|
return DropEffect.None; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Drop(IDataObject data, int index, DropEffect finalEffect) |
||||||
|
{ |
||||||
|
var paths = data.GetData(typeof(string[])) as string[]; |
||||||
|
if (paths != null) { |
||||||
|
for (int i = 0; i < paths.Length; i++) { |
||||||
|
var p = paths[i]; |
||||||
|
if (File.Exists(p)) { |
||||||
|
Children.Insert(index + i, new FileNode(p)); |
||||||
|
} |
||||||
|
else { |
||||||
|
Children.Insert(index + i, new FolderNode(p)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<PropertyGroup> |
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||||
|
<ProductVersion>9.0.30729</ProductVersion> |
||||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||||
|
<ProjectGuid>{B521D667-3613-429C-AB58-26A5B5A82004}</ProjectGuid> |
||||||
|
<OutputType>WinExe</OutputType> |
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||||
|
<RootNamespace>ICSharpCode.TreeView.Demo</RootNamespace> |
||||||
|
<AssemblyName>ICSharpCode.TreeView.Demo</AssemblyName> |
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> |
||||||
|
<FileAlignment>512</FileAlignment> |
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||||
|
<DebugSymbols>true</DebugSymbols> |
||||||
|
<DebugType>full</DebugType> |
||||||
|
<Optimize>false</Optimize> |
||||||
|
<OutputPath>bin\Debug\</OutputPath> |
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||||
|
<DebugType>pdbonly</DebugType> |
||||||
|
<Optimize>true</Optimize> |
||||||
|
<OutputPath>bin\Release\</OutputPath> |
||||||
|
<DefineConstants>TRACE</DefineConstants> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
</PropertyGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Reference Include="System" /> |
||||||
|
<Reference Include="System.Core"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Xml.Linq"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Data.DataSetExtensions"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Data" /> |
||||||
|
<Reference Include="System.Xml" /> |
||||||
|
<Reference Include="WindowsBase" /> |
||||||
|
<Reference Include="PresentationCore" /> |
||||||
|
<Reference Include="PresentationFramework" /> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<ApplicationDefinition Include="App.xaml"> |
||||||
|
<Generator>MSBuild:Compile</Generator> |
||||||
|
<SubType>Designer</SubType> |
||||||
|
</ApplicationDefinition> |
||||||
|
<Page Include="Window1.xaml"> |
||||||
|
<Generator>MSBuild:Compile</Generator> |
||||||
|
<SubType>Designer</SubType> |
||||||
|
</Page> |
||||||
|
<Compile Include="App.xaml.cs"> |
||||||
|
<DependentUpon>App.xaml</DependentUpon> |
||||||
|
<SubType>Code</SubType> |
||||||
|
</Compile> |
||||||
|
<Compile Include="Window1.xaml.cs"> |
||||||
|
<DependentUpon>Window1.xaml</DependentUpon> |
||||||
|
<SubType>Code</SubType> |
||||||
|
</Compile> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs"> |
||||||
|
<Link>Properties\GlobalAssemblyInfo.cs</Link> |
||||||
|
</Compile> |
||||||
|
<Compile Include="FileNode.cs" /> |
||||||
|
<Compile Include="FileSystemNode.cs" /> |
||||||
|
<Compile Include="FolderNode.cs" /> |
||||||
|
<Compile Include="Properties\AssemblyInfo.cs"> |
||||||
|
<SubType>Code</SubType> |
||||||
|
</Compile> |
||||||
|
<AppDesigner Include="Properties\" /> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\ICSharpCode.TreeView\ICSharpCode.TreeView.csproj"> |
||||||
|
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project> |
||||||
|
<Name>ICSharpCode.TreeView</Name> |
||||||
|
</ProjectReference> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Resource Include="Images\File.png" /> |
||||||
|
<Resource Include="Images\Folder.png" /> |
||||||
|
<Resource Include="Images\FolderOpened.png" /> |
||||||
|
</ItemGroup> |
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
||||||
|
Other similar extension points exist, see Microsoft.Common.targets. |
||||||
|
<Target Name="BeforeBuild"> |
||||||
|
</Target> |
||||||
|
<Target Name="AfterBuild"> |
||||||
|
</Target> |
||||||
|
--> |
||||||
|
</Project> |
After Width: | Height: | Size: 294 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,46 @@ |
|||||||
|
using System.Reflection; |
||||||
|
using System.Resources; |
||||||
|
using System.Runtime.CompilerServices; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("ICSharpCode.TreeView.Demo")] |
||||||
|
[assembly: AssemblyDescription("")] |
||||||
|
[assembly: AssemblyConfiguration("")] |
||||||
|
[assembly: AssemblyTrademark("")] |
||||||
|
[assembly: AssemblyCulture("")] |
||||||
|
|
||||||
|
//In order to begin building localizable applications, set
|
||||||
|
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||||
|
//inside a <PropertyGroup>. For example, if you are using US english
|
||||||
|
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||||
|
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||||
|
//the line below to match the UICulture setting in the project file.
|
||||||
|
|
||||||
|
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||||
|
|
||||||
|
|
||||||
|
[assembly: ThemeInfo( |
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)] |
||||||
|
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")] |
@ -0,0 +1,67 @@ |
|||||||
|
<Window x:Class="ICSharpCode.TreeView.Demo.Window1" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:sd="http://sharpdevelop.net" |
||||||
|
Title="SharpTreeView Demo" |
||||||
|
SnapsToDevicePixels="True" |
||||||
|
Background="{x:Static SystemColors.ControlBrush}"> |
||||||
|
|
||||||
|
<DockPanel Margin="10"> |
||||||
|
|
||||||
|
<TextBlock DockPanel.Dock="Top" |
||||||
|
Height="70"> |
||||||
|
Features: MVVM (POCO variant), Multiselect, Drag and Drop (with or without order), Cut / Copy / Paste / Delete, Rename (try rename file to '?'),<LineBreak /> |
||||||
|
VirtualizationMode.Recycling (by default), Root Lines, Columns (using ListView), Icon, Checkbox, ContextMenu, Lazy Loading.<LineBreak /> |
||||||
|
<LineBreak /> |
||||||
|
<Run FontWeight="Bold">Changes does not affect real file system.</Run> |
||||||
|
</TextBlock> |
||||||
|
<Grid> |
||||||
|
|
||||||
|
<Grid.ColumnDefinitions> |
||||||
|
<ColumnDefinition /> |
||||||
|
<ColumnDefinition /> |
||||||
|
</Grid.ColumnDefinitions> |
||||||
|
|
||||||
|
<sd:SharpTreeView x:Name="treeView1" |
||||||
|
AllowDrop="True" |
||||||
|
AllowDropOrder="True" /> |
||||||
|
|
||||||
|
<sd:SharpTreeView x:Name="treeView2" |
||||||
|
AllowDrop="True" |
||||||
|
ShowAlternation="True" |
||||||
|
Grid.Column="1" |
||||||
|
Margin="10 0 0 0"> |
||||||
|
<ListView.View> |
||||||
|
<GridView> |
||||||
|
<GridView.Columns> |
||||||
|
<GridViewColumn> |
||||||
|
<GridViewColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<sd:SharpTreeNodeView /> |
||||||
|
</DataTemplate> |
||||||
|
</GridViewColumn.CellTemplate> |
||||||
|
</GridViewColumn> |
||||||
|
<GridViewColumn Header="File Size"> |
||||||
|
<GridViewColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<TextBlock Text="{Binding FileSize}" /> |
||||||
|
</DataTemplate> |
||||||
|
</GridViewColumn.CellTemplate> |
||||||
|
</GridViewColumn> |
||||||
|
<GridViewColumn Header="File Modified"> |
||||||
|
<GridViewColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<TextBlock Text="{Binding FileModified}" /> |
||||||
|
</DataTemplate> |
||||||
|
</GridViewColumn.CellTemplate> |
||||||
|
</GridViewColumn> |
||||||
|
</GridView.Columns> |
||||||
|
</GridView> |
||||||
|
</ListView.View> |
||||||
|
|
||||||
|
</sd:SharpTreeView> |
||||||
|
|
||||||
|
</Grid> |
||||||
|
</DockPanel> |
||||||
|
|
||||||
|
</Window> |
@ -0,0 +1,48 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Windows.Media.Imaging; |
||||||
|
using System.Windows.Navigation; |
||||||
|
using System.Windows.Shapes; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView.Demo |
||||||
|
{ |
||||||
|
public partial class Window1 : Window |
||||||
|
{ |
||||||
|
public Window1() |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
|
||||||
|
treeView1.Root = new FolderNode("c:\\"); |
||||||
|
//treeView1.SelectionChanged += new SelectionChangedEventHandler(treeView1_SelectionChanged);
|
||||||
|
|
||||||
|
treeView2.Root = new FolderNode("c:\\"); |
||||||
|
} |
||||||
|
|
||||||
|
//void treeView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
//{
|
||||||
|
// //Debug.WriteLine(treeView1.SelectedItems.Count);
|
||||||
|
|
||||||
|
// StringBuilder sb = new StringBuilder();
|
||||||
|
// foreach (var item in SharpTreeNode.ActiveNodes) {
|
||||||
|
// sb.Append(item.ToString() + "; ");
|
||||||
|
// }
|
||||||
|
// Debug.WriteLine(sb.ToString());
|
||||||
|
//}
|
||||||
|
|
||||||
|
public static Image LoadIcon(string name) |
||||||
|
{ |
||||||
|
var frame = BitmapFrame.Create(new Uri("pack://application:,,,/Images/" + name, UriKind.Absolute)); |
||||||
|
Image result = new Image(); |
||||||
|
result.Source = frame; |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Markup; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Globalization; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class CollapsedWhenFalse : MarkupExtension, IValueConverter |
||||||
|
{ |
||||||
|
public static CollapsedWhenFalse Instance = new CollapsedWhenFalse(); |
||||||
|
|
||||||
|
public override object ProvideValue(IServiceProvider serviceProvider) |
||||||
|
{ |
||||||
|
return Instance; |
||||||
|
} |
||||||
|
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||||
|
{ |
||||||
|
return (bool)value ? Visibility.Visible : Visibility.Collapsed; |
||||||
|
} |
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public enum DropEffect |
||||||
|
{ |
||||||
|
None, Move, Copy, Link |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
class EditTextBox : TextBox |
||||||
|
{ |
||||||
|
static EditTextBox() |
||||||
|
{ |
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(EditTextBox), |
||||||
|
new FrameworkPropertyMetadata(typeof(EditTextBox))); |
||||||
|
} |
||||||
|
|
||||||
|
public EditTextBox() |
||||||
|
{ |
||||||
|
Loaded += delegate { Init(); }; |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeViewItem Item { get; set; } |
||||||
|
|
||||||
|
public SharpTreeNode Node |
||||||
|
{ |
||||||
|
get { return Item.Node; } |
||||||
|
} |
||||||
|
|
||||||
|
void Init() |
||||||
|
{ |
||||||
|
Text = Node.LoadEditText(); |
||||||
|
Focus(); |
||||||
|
SelectAll(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e) |
||||||
|
{ |
||||||
|
if (e.Key == Key.Enter) { |
||||||
|
Commit(); |
||||||
|
} |
||||||
|
else if (e.Key == Key.Escape) { |
||||||
|
Node.IsEditing = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) |
||||||
|
{ |
||||||
|
if (Node.IsEditing) { |
||||||
|
Commit(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool commiting; |
||||||
|
|
||||||
|
void Commit() |
||||||
|
{ |
||||||
|
if (!commiting) { |
||||||
|
commiting = true; |
||||||
|
|
||||||
|
Node.IsEditing = false; |
||||||
|
if (!Node.SaveEditText(Text)) { |
||||||
|
Item.Focus(); |
||||||
|
} |
||||||
|
Node.RaisePropertyChanged("Text"); |
||||||
|
|
||||||
|
//if (Node.SaveEditText(Text)) {
|
||||||
|
// Node.IsEditing = false;
|
||||||
|
// Node.RaisePropertyChanged("Text");
|
||||||
|
//}
|
||||||
|
//else {
|
||||||
|
// Init();
|
||||||
|
//}
|
||||||
|
|
||||||
|
commiting = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Windows; |
||||||
|
using System.Collections; |
||||||
|
using System.Windows.Input; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public static class ExtensionMethods |
||||||
|
{ |
||||||
|
public static T FindAncestor<T>(this DependencyObject d) where T : class |
||||||
|
{ |
||||||
|
return AncestorsAndSelf(d).OfType<T>().FirstOrDefault(); |
||||||
|
} |
||||||
|
|
||||||
|
public static IEnumerable<DependencyObject> AncestorsAndSelf(this DependencyObject d) |
||||||
|
{ |
||||||
|
while (d != null) { |
||||||
|
yield return d; |
||||||
|
d = VisualTreeHelper.GetParent(d); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void AddOnce(this IList list, object item) |
||||||
|
{ |
||||||
|
if (!list.Contains(item)) { |
||||||
|
list.Add(item); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class GeneralAdorner : Adorner |
||||||
|
{ |
||||||
|
public GeneralAdorner(UIElement target) |
||||||
|
: base(target) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
FrameworkElement child; |
||||||
|
|
||||||
|
public FrameworkElement Child |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return child; |
||||||
|
} |
||||||
|
set |
||||||
|
{ |
||||||
|
if (child != value) { |
||||||
|
RemoveVisualChild(child); |
||||||
|
RemoveLogicalChild(child); |
||||||
|
child = value; |
||||||
|
AddLogicalChild(value); |
||||||
|
AddVisualChild(value); |
||||||
|
InvalidateMeasure(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override int VisualChildrenCount |
||||||
|
{ |
||||||
|
get { return child == null ? 0 : 1; } |
||||||
|
} |
||||||
|
|
||||||
|
protected override Visual GetVisualChild(int index) |
||||||
|
{ |
||||||
|
return child; |
||||||
|
} |
||||||
|
|
||||||
|
protected override Size MeasureOverride(Size constraint) |
||||||
|
{ |
||||||
|
if (child != null) { |
||||||
|
child.Measure(constraint); |
||||||
|
return child.DesiredSize; |
||||||
|
} |
||||||
|
return new Size(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override Size ArrangeOverride(Size finalSize) |
||||||
|
{ |
||||||
|
if (child != null) { |
||||||
|
child.Arrange(new Rect(finalSize)); |
||||||
|
return finalSize; |
||||||
|
} |
||||||
|
return new Size(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,89 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<PropertyGroup> |
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||||
|
<ProductVersion>9.0.30729</ProductVersion> |
||||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||||
|
<ProjectGuid>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</ProjectGuid> |
||||||
|
<OutputType>library</OutputType> |
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||||
|
<RootNamespace>ICSharpCode.TreeView</RootNamespace> |
||||||
|
<AssemblyName>ICSharpCode.TreeView</AssemblyName> |
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> |
||||||
|
<FileAlignment>512</FileAlignment> |
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
<OutputPath>..\..\..\..\bin\</OutputPath> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||||
|
<DebugSymbols>true</DebugSymbols> |
||||||
|
<DebugType>full</DebugType> |
||||||
|
<Optimize>false</Optimize> |
||||||
|
<OutputPath>..\..\..\..\bin\</OutputPath> |
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||||
|
<DebugType>pdbonly</DebugType> |
||||||
|
<Optimize>true</Optimize> |
||||||
|
<OutputPath>..\..\..\..\bin\</OutputPath> |
||||||
|
<DefineConstants>TRACE</DefineConstants> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
</PropertyGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Reference Include="System" /> |
||||||
|
<Reference Include="System.Core"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Xml.Linq"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Data.DataSetExtensions"> |
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||||
|
</Reference> |
||||||
|
<Reference Include="System.Data" /> |
||||||
|
<Reference Include="System.Xml" /> |
||||||
|
<Reference Include="WindowsBase" /> |
||||||
|
<Reference Include="PresentationCore" /> |
||||||
|
<Reference Include="PresentationFramework" /> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Page Include="Themes\Generic.xaml"> |
||||||
|
<Generator>MSBuild:Compile</Generator> |
||||||
|
<SubType>Designer</SubType> |
||||||
|
</Page> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs"> |
||||||
|
<Link>Properties\GlobalAssemblyInfo.cs</Link> |
||||||
|
</Compile> |
||||||
|
<Compile Include="Converters.cs" /> |
||||||
|
<Compile Include="DropEffect.cs" /> |
||||||
|
<Compile Include="EditTextBox.cs" /> |
||||||
|
<Compile Include="ExtensionMethods.cs" /> |
||||||
|
<Compile Include="GeneralAdorner.cs" /> |
||||||
|
<Compile Include="InsertMarker.cs" /> |
||||||
|
<Compile Include="LinesRenderer.cs" /> |
||||||
|
<Compile Include="Properties\AssemblyInfo.cs"> |
||||||
|
<SubType>Code</SubType> |
||||||
|
</Compile> |
||||||
|
<Compile Include="SharpTreeNode.cs" /> |
||||||
|
<Compile Include="SharpTreeNodeCollection.cs" /> |
||||||
|
<Compile Include="SharpTreeNodeView.cs" /> |
||||||
|
<Compile Include="SharpTreeView.cs" /> |
||||||
|
<Compile Include="SharpTreeViewItem.cs" /> |
||||||
|
<Compile Include="TreeFlattener.cs" /> |
||||||
|
<AppDesigner Include="Properties\" /> |
||||||
|
</ItemGroup> |
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
||||||
|
Other similar extension points exist, see Microsoft.Common.targets. |
||||||
|
<Target Name="BeforeBuild"> |
||||||
|
</Target> |
||||||
|
<Target Name="AfterBuild"> |
||||||
|
</Target> |
||||||
|
--> |
||||||
|
</Project> |
@ -0,0 +1,18 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class InsertMarker : Control |
||||||
|
{ |
||||||
|
static InsertMarker() |
||||||
|
{ |
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(InsertMarker), |
||||||
|
new FrameworkPropertyMetadata(typeof(InsertMarker))); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
class LinesRenderer : FrameworkElement |
||||||
|
{ |
||||||
|
static LinesRenderer() |
||||||
|
{ |
||||||
|
pen = new Pen(Brushes.LightGray, 1); |
||||||
|
pen.Freeze(); |
||||||
|
} |
||||||
|
|
||||||
|
static Pen pen; |
||||||
|
|
||||||
|
SharpTreeNodeView NodeView |
||||||
|
{ |
||||||
|
get { return TemplatedParent as SharpTreeNodeView; } |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnRender(DrawingContext dc) |
||||||
|
{ |
||||||
|
var indent = NodeView.CalculateIndent(); |
||||||
|
if (indent == 0) return; |
||||||
|
|
||||||
|
var p = new Point(indent + 4.5, 0); |
||||||
|
|
||||||
|
if (NodeView.Node.IsLast) { |
||||||
|
dc.DrawLine(pen, p, new Point(p.X, ActualHeight / 2)); |
||||||
|
} |
||||||
|
else { |
||||||
|
dc.DrawLine(pen, p, new Point(p.X, ActualHeight)); |
||||||
|
} |
||||||
|
|
||||||
|
dc.DrawLine(pen, new Point(p.X, ActualHeight / 2), new Point(p.X + 10, ActualHeight / 2)); |
||||||
|
|
||||||
|
var current = NodeView.Node; |
||||||
|
while (true) { |
||||||
|
p.X -= 19; |
||||||
|
current = current.Parent; |
||||||
|
if (p.X < 0) break; |
||||||
|
if (!current.IsLast) { |
||||||
|
dc.DrawLine(pen, p, new Point(p.X, ActualHeight)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
using System.Reflection; |
||||||
|
using System.Resources; |
||||||
|
using System.Runtime.CompilerServices; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Markup; |
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("ICSharpCode.TreeView")] |
||||||
|
[assembly: AssemblyDescription("")] |
||||||
|
[assembly: AssemblyConfiguration("")] |
||||||
|
[assembly: AssemblyTrademark("")] |
||||||
|
[assembly: AssemblyCulture("")] |
||||||
|
|
||||||
|
//In order to begin building localizable applications, set
|
||||||
|
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||||
|
//inside a <PropertyGroup>. For example, if you are using US english
|
||||||
|
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||||
|
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||||
|
//the line below to match the UICulture setting in the project file.
|
||||||
|
|
||||||
|
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||||
|
|
||||||
|
|
||||||
|
[assembly: ThemeInfo( |
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)] |
||||||
|
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")] |
||||||
|
|
||||||
|
[assembly: XmlnsPrefix("http://sharpdevelop.net", "sd")] |
||||||
|
|
||||||
|
[assembly: XmlnsDefinition("http://sharpdevelop.net", "ICSharpCode.TreeView")] |
@ -0,0 +1,593 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Collections.Specialized; |
||||||
|
using System.Windows.Input; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class SharpTreeNode : INotifyPropertyChanged |
||||||
|
{ |
||||||
|
#region Main
|
||||||
|
|
||||||
|
static SharpTreeNode() |
||||||
|
{ |
||||||
|
SelectedNodes = new List<SharpTreeNode>(); |
||||||
|
ActiveNodes = new List<SharpTreeNode>(); |
||||||
|
StartCuttedDataWatcher(); |
||||||
|
} |
||||||
|
|
||||||
|
public static List<SharpTreeNode> SelectedNodes { get; private set; } |
||||||
|
public static List<SharpTreeNode> ActiveNodes { get; private set; } |
||||||
|
|
||||||
|
static SharpTreeNode[] ActiveNodesArray |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return ActiveNodes.ToArray(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeNode() |
||||||
|
{ |
||||||
|
Children = new SharpTreeNodeCollection(this); |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeNodeCollection Children { get; private set; } |
||||||
|
public SharpTreeNode Parent { get; internal set; } |
||||||
|
|
||||||
|
public virtual object Text |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
public virtual object Icon |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
public virtual object ToolTip |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
public int Level |
||||||
|
{ |
||||||
|
get { return Parent != null ? Parent.Level + 1 : 0; } |
||||||
|
} |
||||||
|
|
||||||
|
//bool isSelected;
|
||||||
|
|
||||||
|
//public bool IsSelected
|
||||||
|
//{
|
||||||
|
// get { return isSelected; }
|
||||||
|
// set
|
||||||
|
// {
|
||||||
|
// isSelected = value;
|
||||||
|
// RaisePropertyChanged("IsSelected");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
public virtual ContextMenu GetContextMenu() |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
internal protected void OnChildrenChanged(NotifyCollectionChangedEventArgs e) |
||||||
|
{ |
||||||
|
RaisePropertyChanged("ShowExpander"); |
||||||
|
RaiseIsLastChangedIfNeeded(e); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Expanding / LazyLoading
|
||||||
|
|
||||||
|
public event EventHandler Collapsing; |
||||||
|
|
||||||
|
public virtual object ExpandedIcon |
||||||
|
{ |
||||||
|
get { return Icon; } |
||||||
|
} |
||||||
|
|
||||||
|
public virtual bool ShowExpander |
||||||
|
{ |
||||||
|
get { return Children.Count > 0 || LazyLoading; } |
||||||
|
} |
||||||
|
|
||||||
|
//public virtual bool ShowLoading
|
||||||
|
//{
|
||||||
|
// get { return false; }
|
||||||
|
//}
|
||||||
|
|
||||||
|
bool isExpanded; |
||||||
|
|
||||||
|
public bool IsExpanded |
||||||
|
{ |
||||||
|
get { return isExpanded; } |
||||||
|
set |
||||||
|
{ |
||||||
|
if (isExpanded != value) { |
||||||
|
isExpanded = value; |
||||||
|
if (isExpanded) { |
||||||
|
EnsureLazyChildren(); |
||||||
|
} |
||||||
|
else { |
||||||
|
if (Collapsing != null) { |
||||||
|
Collapsing(this, EventArgs.Empty); |
||||||
|
} |
||||||
|
} |
||||||
|
RaisePropertyChanged("IsExpanded"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool lazyLoading; |
||||||
|
|
||||||
|
public bool LazyLoading |
||||||
|
{ |
||||||
|
get { return lazyLoading; } |
||||||
|
set |
||||||
|
{ |
||||||
|
lazyLoading = value; |
||||||
|
if (lazyLoading) { |
||||||
|
IsExpanded = false; |
||||||
|
} |
||||||
|
RaisePropertyChanged("LazyLoading"); |
||||||
|
RaisePropertyChanged("ShowExpander"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public virtual void LoadChildren() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public void EnsureLazyChildren() |
||||||
|
{ |
||||||
|
if (LazyLoading) { |
||||||
|
LoadChildren(); |
||||||
|
LazyLoading = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Ancestors / Descendants
|
||||||
|
|
||||||
|
public IEnumerable<SharpTreeNode> Descendants() |
||||||
|
{ |
||||||
|
foreach (var child in Children) { |
||||||
|
foreach (var child2 in child.DescendantsAndSelf()) { |
||||||
|
yield return child2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<SharpTreeNode> DescendantsAndSelf() |
||||||
|
{ |
||||||
|
yield return this; |
||||||
|
foreach (var child in Descendants()) { |
||||||
|
yield return child; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<SharpTreeNode> ExpandedDescendants() |
||||||
|
{ |
||||||
|
foreach (var child in Children) { |
||||||
|
foreach (var child2 in child.ExpandedDescendantsAndSelf()) { |
||||||
|
yield return child2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<SharpTreeNode> ExpandedDescendantsAndSelf() |
||||||
|
{ |
||||||
|
yield return this; |
||||||
|
if (IsExpanded) { |
||||||
|
foreach (var child in Children) { |
||||||
|
foreach (var child2 in child.ExpandedDescendantsAndSelf()) { |
||||||
|
yield return child2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<SharpTreeNode> Ancestors() |
||||||
|
{ |
||||||
|
var node = this; |
||||||
|
while (node.Parent != null) { |
||||||
|
yield return node.Parent; |
||||||
|
node = node.Parent; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<SharpTreeNode> AncestorsAndSelf() |
||||||
|
{ |
||||||
|
yield return this; |
||||||
|
foreach (var node in Ancestors()) { |
||||||
|
yield return node; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Editing
|
||||||
|
|
||||||
|
public virtual bool IsEditable |
||||||
|
{ |
||||||
|
get { return false; } |
||||||
|
} |
||||||
|
|
||||||
|
bool isEditing; |
||||||
|
|
||||||
|
public bool IsEditing |
||||||
|
{ |
||||||
|
get { return isEditing; } |
||||||
|
set |
||||||
|
{ |
||||||
|
if (isEditing != value) { |
||||||
|
isEditing = value; |
||||||
|
RaisePropertyChanged("IsEditing"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public virtual string LoadEditText() |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual bool SaveEditText(string value) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Checkboxes
|
||||||
|
|
||||||
|
public virtual bool IsCheckable |
||||||
|
{ |
||||||
|
get { return false; } |
||||||
|
} |
||||||
|
|
||||||
|
bool? isChecked; |
||||||
|
|
||||||
|
public bool? IsChecked |
||||||
|
{ |
||||||
|
get { return isChecked; } |
||||||
|
set |
||||||
|
{ |
||||||
|
SetIsChecked(value, true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void SetIsChecked(bool? value, bool update) |
||||||
|
{ |
||||||
|
if (isChecked != value) { |
||||||
|
isChecked = value; |
||||||
|
|
||||||
|
if (update) { |
||||||
|
if (IsChecked != null) { |
||||||
|
foreach (var child in Descendants()) { |
||||||
|
if (child.IsCheckable) { |
||||||
|
child.SetIsChecked(IsChecked, false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
foreach (var parent in Ancestors()) { |
||||||
|
if (parent.IsCheckable) { |
||||||
|
if (!parent.TryValueForIsChecked(true)) { |
||||||
|
if (!parent.TryValueForIsChecked(false)) { |
||||||
|
parent.SetIsChecked(null, false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
RaisePropertyChanged("IsChecked"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool TryValueForIsChecked(bool? value) |
||||||
|
{ |
||||||
|
if (Children.Where(n => n.IsCheckable).All(n => n.IsChecked == value)) { |
||||||
|
SetIsChecked(value, false); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Cut / Copy / Paste / Delete
|
||||||
|
|
||||||
|
static List<SharpTreeNode> cuttedNodes = new List<SharpTreeNode>(); |
||||||
|
static IDataObject cuttedData; |
||||||
|
static EventHandler requerySuggestedHandler; // for weak event
|
||||||
|
|
||||||
|
static void StartCuttedDataWatcher() |
||||||
|
{ |
||||||
|
requerySuggestedHandler = new EventHandler(CommandManager_RequerySuggested); |
||||||
|
CommandManager.RequerySuggested += requerySuggestedHandler; |
||||||
|
} |
||||||
|
|
||||||
|
static void CommandManager_RequerySuggested(object sender, EventArgs e) |
||||||
|
{ |
||||||
|
if (cuttedData != null && !Clipboard.IsCurrent(cuttedData)) { |
||||||
|
ClearCuttedData(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void ClearCuttedData() |
||||||
|
{ |
||||||
|
foreach (var node in cuttedNodes) { |
||||||
|
node.IsCut = false; |
||||||
|
} |
||||||
|
cuttedNodes.Clear(); |
||||||
|
cuttedData = null; |
||||||
|
} |
||||||
|
|
||||||
|
//static public IEnumerable<SharpTreeNode> PurifyNodes(IEnumerable<SharpTreeNode> nodes)
|
||||||
|
//{
|
||||||
|
// var list = nodes.ToList();
|
||||||
|
// var array = list.ToArray();
|
||||||
|
// foreach (var node1 in array) {
|
||||||
|
// foreach (var node2 in array) {
|
||||||
|
// if (node1.Descendants().Contains(node2)) {
|
||||||
|
// list.Remove(node2);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return list;
|
||||||
|
//}
|
||||||
|
|
||||||
|
bool isCut; |
||||||
|
|
||||||
|
public bool IsCut |
||||||
|
{ |
||||||
|
get { return isCut; } |
||||||
|
private set |
||||||
|
{ |
||||||
|
isCut = value; |
||||||
|
RaisePropertyChanged("IsCut"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal bool InternalCanCut() |
||||||
|
{ |
||||||
|
return InternalCanCopy() && InternalCanDelete(); |
||||||
|
} |
||||||
|
|
||||||
|
internal void InternalCut() |
||||||
|
{ |
||||||
|
ClearCuttedData(); |
||||||
|
cuttedData = Copy(ActiveNodesArray); |
||||||
|
Clipboard.SetDataObject(cuttedData); |
||||||
|
|
||||||
|
foreach (var node in ActiveNodes) { |
||||||
|
node.IsCut = true; |
||||||
|
cuttedNodes.Add(node); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal bool InternalCanCopy() |
||||||
|
{ |
||||||
|
return CanCopy(ActiveNodesArray); |
||||||
|
} |
||||||
|
|
||||||
|
internal void InternalCopy() |
||||||
|
{ |
||||||
|
Clipboard.SetDataObject(Copy(ActiveNodesArray)); |
||||||
|
} |
||||||
|
|
||||||
|
internal bool InternalCanPaste() |
||||||
|
{ |
||||||
|
return CanPaste(Clipboard.GetDataObject()); |
||||||
|
} |
||||||
|
|
||||||
|
internal void InternalPaste() |
||||||
|
{ |
||||||
|
Paste(Clipboard.GetDataObject()); |
||||||
|
|
||||||
|
if (cuttedData != null) { |
||||||
|
DeleteCore(cuttedNodes.ToArray()); |
||||||
|
ClearCuttedData(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal bool InternalCanDelete() |
||||||
|
{ |
||||||
|
return CanDelete(ActiveNodesArray); |
||||||
|
} |
||||||
|
|
||||||
|
internal void InternalDelete() |
||||||
|
{ |
||||||
|
Delete(ActiveNodesArray); |
||||||
|
} |
||||||
|
|
||||||
|
public virtual bool CanDelete(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual void Delete(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public virtual void DeleteCore(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public virtual bool CanCopy(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual IDataObject Copy(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual bool CanPaste(IDataObject data) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual void Paste(IDataObject data) |
||||||
|
{ |
||||||
|
EnsureLazyChildren(); |
||||||
|
Drop(data, Children.Count, DropEffect.Copy); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Drag and Drop
|
||||||
|
|
||||||
|
internal bool InternalCanDrag() |
||||||
|
{ |
||||||
|
return CanDrag(ActiveNodesArray); |
||||||
|
} |
||||||
|
|
||||||
|
internal void InternalDrag(DependencyObject dragSource) |
||||||
|
{ |
||||||
|
DragDrop.DoDragDrop(dragSource, Copy(ActiveNodesArray), DragDropEffects.All); |
||||||
|
} |
||||||
|
|
||||||
|
internal bool InternalCanDrop(DragEventArgs e, int index) |
||||||
|
{ |
||||||
|
var finalEffect = GetFinalEffect(e, index); |
||||||
|
e.Effects = GetDragDropEffects(finalEffect); |
||||||
|
return finalEffect != DropEffect.None; |
||||||
|
} |
||||||
|
|
||||||
|
internal void InternalDrop(DragEventArgs e, int index) |
||||||
|
{ |
||||||
|
if (LazyLoading) { |
||||||
|
EnsureLazyChildren(); |
||||||
|
index = Children.Count; |
||||||
|
} |
||||||
|
|
||||||
|
var finalEffect = GetFinalEffect(e, index); |
||||||
|
Drop(e.Data, index, finalEffect); |
||||||
|
|
||||||
|
if (finalEffect == DropEffect.Move) { |
||||||
|
DeleteCore(ActiveNodesArray); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
DropEffect GetFinalEffect(DragEventArgs e, int index) |
||||||
|
{ |
||||||
|
var requestedEffect = GetDropEffect(e); |
||||||
|
var result = CanDrop(e.Data, requestedEffect); |
||||||
|
if (result == DropEffect.Move) { |
||||||
|
if (!CanDelete(ActiveNodesArray)) { |
||||||
|
return DropEffect.None; |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
static DropEffect GetDropEffect(DragEventArgs e) |
||||||
|
{ |
||||||
|
if (e.Data != null) { |
||||||
|
var all = DragDropKeyStates.ControlKey | DragDropKeyStates.ShiftKey | DragDropKeyStates.AltKey; |
||||||
|
|
||||||
|
if ((e.KeyStates & all) == DragDropKeyStates.ControlKey) { |
||||||
|
return DropEffect.Copy; |
||||||
|
} |
||||||
|
if ((e.KeyStates & all) == DragDropKeyStates.AltKey) { |
||||||
|
return DropEffect.Link; |
||||||
|
} |
||||||
|
if ((e.KeyStates & all) == (DragDropKeyStates.ControlKey | DragDropKeyStates.ShiftKey)) { |
||||||
|
return DropEffect.Link; |
||||||
|
} |
||||||
|
return DropEffect.Move; |
||||||
|
} |
||||||
|
return DropEffect.None; |
||||||
|
} |
||||||
|
|
||||||
|
static DragDropEffects GetDragDropEffects(DropEffect effect) |
||||||
|
{ |
||||||
|
switch (effect) { |
||||||
|
case DropEffect.Copy: |
||||||
|
return DragDropEffects.Copy; |
||||||
|
case DropEffect.Link: |
||||||
|
return DragDropEffects.Link; |
||||||
|
case DropEffect.Move: |
||||||
|
return DragDropEffects.Move; |
||||||
|
} |
||||||
|
return DragDropEffects.None; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual bool CanDrag(SharpTreeNode[] nodes) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual DropEffect CanDrop(IDataObject data, DropEffect requestedEffect) |
||||||
|
{ |
||||||
|
return DropEffect.None; |
||||||
|
} |
||||||
|
|
||||||
|
public virtual void Drop(IDataObject data, int index, DropEffect finalEffect) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IsLast (for TreeView lines)
|
||||||
|
|
||||||
|
public bool IsLast |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return Parent == null || |
||||||
|
Parent.Children[Parent.Children.Count - 1] == this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RaiseIsLastChangedIfNeeded(NotifyCollectionChangedEventArgs e) |
||||||
|
{ |
||||||
|
switch (e.Action) { |
||||||
|
case NotifyCollectionChangedAction.Add: |
||||||
|
if (e.NewStartingIndex == Children.Count - 1) { |
||||||
|
if (Children.Count > 1) { |
||||||
|
Children[Children.Count - 2].RaisePropertyChanged("IsLast"); |
||||||
|
} |
||||||
|
Children[Children.Count - 1].RaisePropertyChanged("IsLast"); |
||||||
|
} |
||||||
|
break; |
||||||
|
case NotifyCollectionChangedAction.Remove: |
||||||
|
if (e.OldStartingIndex == Children.Count) { |
||||||
|
if (Children.Count > 0) { |
||||||
|
Children[Children.Count - 1].RaisePropertyChanged("IsLast"); |
||||||
|
} |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region INotifyPropertyChanged Members
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged; |
||||||
|
|
||||||
|
public void RaisePropertyChanged(string name) |
||||||
|
{ |
||||||
|
if (PropertyChanged != null) { |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(name)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.Collections.Specialized; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class SharpTreeNodeCollection : ObservableCollection<SharpTreeNode> |
||||||
|
{ |
||||||
|
public SharpTreeNodeCollection(SharpTreeNode parent) |
||||||
|
{ |
||||||
|
Parent = parent; |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeNode Parent { get; private set; } |
||||||
|
|
||||||
|
protected override void InsertItem(int index, SharpTreeNode node) |
||||||
|
{ |
||||||
|
node.Parent = Parent; |
||||||
|
base.InsertItem(index, node); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void RemoveItem(int index) |
||||||
|
{ |
||||||
|
var node = this[index]; |
||||||
|
node.Parent = null; |
||||||
|
base.RemoveItem(index); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void ClearItems() |
||||||
|
{ |
||||||
|
foreach (var node in this) { |
||||||
|
node.Parent = null; |
||||||
|
} |
||||||
|
base.ClearItems(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) |
||||||
|
{ |
||||||
|
base.OnCollectionChanged(e); |
||||||
|
Parent.OnChildrenChanged(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,146 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls.Primitives; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.Collections.Specialized; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class SharpTreeNodeView : Control |
||||||
|
{ |
||||||
|
static SharpTreeNodeView() |
||||||
|
{ |
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeNodeView), |
||||||
|
new FrameworkPropertyMetadata(typeof(SharpTreeNodeView))); |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty TextBackgroundProperty = |
||||||
|
DependencyProperty.Register("TextBackground", typeof(Brush), typeof(SharpTreeNodeView)); |
||||||
|
|
||||||
|
public Brush TextBackground |
||||||
|
{ |
||||||
|
get { return (Brush)GetValue(TextBackgroundProperty); } |
||||||
|
set { SetValue(TextBackgroundProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeNode Node |
||||||
|
{ |
||||||
|
get { return DataContext as SharpTreeNode; } |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeViewItem ParentItem { get; private set; } |
||||||
|
|
||||||
|
public SharpTreeView ParentTreeView |
||||||
|
{ |
||||||
|
get { return ParentItem.ParentTreeView; } |
||||||
|
} |
||||||
|
|
||||||
|
internal LinesRenderer LinesRenderer { get; private set; } |
||||||
|
|
||||||
|
public override void OnApplyTemplate() |
||||||
|
{ |
||||||
|
base.OnApplyTemplate(); |
||||||
|
LinesRenderer = Template.FindName("linesRenderer", this) as LinesRenderer; |
||||||
|
UpdateTemplate(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnVisualParentChanged(DependencyObject oldParent) |
||||||
|
{ |
||||||
|
base.OnVisualParentChanged(oldParent); |
||||||
|
ParentItem = this.FindAncestor<SharpTreeViewItem>(); |
||||||
|
ParentItem.NodeView = this; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) |
||||||
|
{ |
||||||
|
base.OnPropertyChanged(e); |
||||||
|
if (e.Property == DataContextProperty) { |
||||||
|
UpdateDataContext(e.OldValue as SharpTreeNode, e.NewValue as SharpTreeNode); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void UpdateDataContext(SharpTreeNode oldNode, SharpTreeNode newNode) |
||||||
|
{ |
||||||
|
if (newNode != null) { |
||||||
|
newNode.Collapsing += Node_Collapsing; |
||||||
|
newNode.PropertyChanged += Node_PropertyChanged; |
||||||
|
if (Template != null) { |
||||||
|
UpdateTemplate(); |
||||||
|
} |
||||||
|
} |
||||||
|
if (oldNode != null) { |
||||||
|
oldNode.Collapsing -= Node_Collapsing; |
||||||
|
oldNode.PropertyChanged -= Node_PropertyChanged; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Node_PropertyChanged(object sender, PropertyChangedEventArgs e) |
||||||
|
{ |
||||||
|
if (e.PropertyName == "IsEditing") { |
||||||
|
OnIsEditingChanged(); |
||||||
|
} |
||||||
|
else if (e.PropertyName == "IsLast") { |
||||||
|
if (ParentTreeView.ShowLines) { |
||||||
|
foreach (var child in Node.ExpandedDescendantsAndSelf()) { |
||||||
|
var container = ParentTreeView.ItemContainerGenerator.ContainerFromItem(child) as SharpTreeViewItem; |
||||||
|
if (container != null) { |
||||||
|
container.NodeView.LinesRenderer.InvalidateVisual(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Node_Collapsing(object sender, EventArgs e) |
||||||
|
{ |
||||||
|
ParentTreeView.HandleCollapsing(Node); |
||||||
|
} |
||||||
|
|
||||||
|
void OnIsEditingChanged() |
||||||
|
{ |
||||||
|
var textEditorContainer = Template.FindName("textEditorContainer", this) as Border; |
||||||
|
if (Node.IsEditing) { |
||||||
|
textEditorContainer.Child = new EditTextBox() { Item = ParentItem }; |
||||||
|
} |
||||||
|
else { |
||||||
|
textEditorContainer.Child = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void UpdateTemplate() |
||||||
|
{ |
||||||
|
var spacer = Template.FindName("spacer", this) as FrameworkElement; |
||||||
|
spacer.Width = CalculateIndent(); |
||||||
|
|
||||||
|
var expander = Template.FindName("expander", this) as ToggleButton; |
||||||
|
if (ParentTreeView.Root == Node && !ParentTreeView.ShowRootExpander) { |
||||||
|
expander.Visibility = Visibility.Collapsed; |
||||||
|
} |
||||||
|
else { |
||||||
|
expander.ClearValue(VisibilityProperty); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal double CalculateIndent() |
||||||
|
{ |
||||||
|
var result = 19 * Node.Level; |
||||||
|
if (ParentTreeView.ShowRoot) { |
||||||
|
if (!ParentTreeView.ShowRootExpander) { |
||||||
|
if (ParentTreeView.Root != Node) { |
||||||
|
result -= 15; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
result -= 19; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,439 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows.Input; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class SharpTreeView : ListView |
||||||
|
{ |
||||||
|
static SharpTreeView() |
||||||
|
{ |
||||||
|
SelectionModeProperty.OverrideMetadata(typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(SelectionMode.Extended)); |
||||||
|
|
||||||
|
AlternationCountProperty.OverrideMetadata(typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(2)); |
||||||
|
|
||||||
|
DefaultItemContainerStyleKey = |
||||||
|
new ComponentResourceKey(typeof(SharpTreeView), "DefaultItemContainerStyleKey"); |
||||||
|
|
||||||
|
VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); |
||||||
|
} |
||||||
|
|
||||||
|
public static ResourceKey DefaultItemContainerStyleKey { get; private set; } |
||||||
|
|
||||||
|
public SharpTreeView() |
||||||
|
{ |
||||||
|
SetResourceReference(ItemContainerStyleProperty, DefaultItemContainerStyleKey); |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty RootProperty = |
||||||
|
DependencyProperty.Register("Root", typeof(SharpTreeNode), typeof(SharpTreeView)); |
||||||
|
|
||||||
|
public SharpTreeNode Root |
||||||
|
{ |
||||||
|
get { return (SharpTreeNode)GetValue(RootProperty); } |
||||||
|
set { SetValue(RootProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty ShowRootProperty = |
||||||
|
DependencyProperty.Register("ShowRoot", typeof(bool), typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(true)); |
||||||
|
|
||||||
|
public bool ShowRoot |
||||||
|
{ |
||||||
|
get { return (bool)GetValue(ShowRootProperty); } |
||||||
|
set { SetValue(ShowRootProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty ShowRootExpanderProperty = |
||||||
|
DependencyProperty.Register("ShowRootExpander", typeof(bool), typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(false)); |
||||||
|
|
||||||
|
public bool ShowRootExpander |
||||||
|
{ |
||||||
|
get { return (bool)GetValue(ShowRootExpanderProperty); } |
||||||
|
set { SetValue(ShowRootExpanderProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty AllowDropOrderProperty = |
||||||
|
DependencyProperty.Register("AllowDropOrder", typeof(bool), typeof(SharpTreeView)); |
||||||
|
|
||||||
|
public bool AllowDropOrder |
||||||
|
{ |
||||||
|
get { return (bool)GetValue(AllowDropOrderProperty); } |
||||||
|
set { SetValue(AllowDropOrderProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty ShowLinesProperty = |
||||||
|
DependencyProperty.Register("ShowLines", typeof(bool), typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(true)); |
||||||
|
|
||||||
|
public bool ShowLines |
||||||
|
{ |
||||||
|
get { return (bool)GetValue(ShowLinesProperty); } |
||||||
|
set { SetValue(ShowLinesProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public static bool GetShowAlternation(DependencyObject obj) |
||||||
|
{ |
||||||
|
return (bool)obj.GetValue(ShowAlternationProperty); |
||||||
|
} |
||||||
|
|
||||||
|
public static void SetShowAlternation(DependencyObject obj, bool value) |
||||||
|
{ |
||||||
|
obj.SetValue(ShowAlternationProperty, value); |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty ShowAlternationProperty = |
||||||
|
DependencyProperty.RegisterAttached("ShowAlternation", typeof(bool), typeof(SharpTreeView), |
||||||
|
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits)); |
||||||
|
|
||||||
|
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) |
||||||
|
{ |
||||||
|
base.OnPropertyChanged(e); |
||||||
|
if (e.Property == RootProperty || |
||||||
|
e.Property == ShowRootProperty || |
||||||
|
e.Property == ShowRootExpanderProperty) { |
||||||
|
Reload(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
TreeFlattener flattener; |
||||||
|
|
||||||
|
void Reload() |
||||||
|
{ |
||||||
|
if (flattener != null) { |
||||||
|
flattener.Stop(); |
||||||
|
} |
||||||
|
if (Root != null) { |
||||||
|
if (!(ShowRoot && ShowRootExpander)) { |
||||||
|
Root.IsExpanded = true; |
||||||
|
} |
||||||
|
flattener = new TreeFlattener(Root, ShowRoot); |
||||||
|
ItemsSource = flattener.List; |
||||||
|
flattener.Start(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override DependencyObject GetContainerForItemOverride() |
||||||
|
{ |
||||||
|
return new SharpTreeViewItem(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override bool IsItemItsOwnContainerOverride(object item) |
||||||
|
{ |
||||||
|
return item is SharpTreeViewItem; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void PrepareContainerForItemOverride(DependencyObject element, object item) |
||||||
|
{ |
||||||
|
base.PrepareContainerForItemOverride(element, item); |
||||||
|
var container = element as SharpTreeViewItem; |
||||||
|
container.ParentTreeView = this; |
||||||
|
} |
||||||
|
|
||||||
|
internal void HandleCollapsing(SharpTreeNode Node) |
||||||
|
{ |
||||||
|
var selectedChilds = Node.Descendants().Where(n => SharpTreeNode.SelectedNodes.Contains(n)); |
||||||
|
if (selectedChilds.Any()) { |
||||||
|
var list = SelectedItems.Cast<SharpTreeNode>().Except(selectedChilds).ToList(); |
||||||
|
list.AddOnce(Node); |
||||||
|
SetSelectedItems(list); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#region Track selection
|
||||||
|
|
||||||
|
protected override void OnSelectionChanged(SelectionChangedEventArgs e) |
||||||
|
{ |
||||||
|
foreach (SharpTreeNode node in e.RemovedItems) { |
||||||
|
SharpTreeNode.SelectedNodes.Remove(node); |
||||||
|
} |
||||||
|
foreach (SharpTreeNode node in e.AddedItems) { |
||||||
|
SharpTreeNode.SelectedNodes.AddOnce(node); |
||||||
|
} |
||||||
|
|
||||||
|
if (IsKeyboardFocusWithin) { |
||||||
|
foreach (SharpTreeNode node in e.RemovedItems) { |
||||||
|
SharpTreeNode.ActiveNodes.Remove(node); |
||||||
|
} |
||||||
|
foreach (SharpTreeNode node in e.AddedItems) { |
||||||
|
SharpTreeNode.ActiveNodes.AddOnce(node); |
||||||
|
} |
||||||
|
SortActiveNodes(); |
||||||
|
} |
||||||
|
base.OnSelectionChanged(e); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e) |
||||||
|
{ |
||||||
|
foreach (SharpTreeNode node in SelectedItems) { |
||||||
|
SharpTreeNode.ActiveNodes.AddOnce(node); |
||||||
|
} |
||||||
|
SortActiveNodes(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e) |
||||||
|
{ |
||||||
|
foreach (SharpTreeNode node in SelectedItems) { |
||||||
|
SharpTreeNode.ActiveNodes.Remove(node); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void SortActiveNodes() |
||||||
|
{ |
||||||
|
SharpTreeNode.ActiveNodes.Sort(delegate(SharpTreeNode n1, SharpTreeNode n2) { |
||||||
|
var index1 = Items.IndexOf(n1); |
||||||
|
var index2 = Items.IndexOf(n2); |
||||||
|
return index1.CompareTo(index2); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Drag and Drop
|
||||||
|
|
||||||
|
protected override void OnDragEnter(DragEventArgs e) |
||||||
|
{ |
||||||
|
e.Effects = DragDropEffects.None; |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnDragOver(DragEventArgs e) |
||||||
|
{ |
||||||
|
e.Effects = DragDropEffects.None; |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
|
||||||
|
internal void HandleDragEnter(SharpTreeViewItem item, DragEventArgs e) |
||||||
|
{ |
||||||
|
HandleDragOver(item, e); |
||||||
|
} |
||||||
|
|
||||||
|
internal void HandleDragOver(SharpTreeViewItem item, DragEventArgs e) |
||||||
|
{ |
||||||
|
HidePreview(); |
||||||
|
e.Handled = true; |
||||||
|
|
||||||
|
var target = GetDropTarget(item, e); |
||||||
|
if (target != null) { |
||||||
|
ShowPreview(target.Item, target.Place); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal void HandleDrop(SharpTreeViewItem item, DragEventArgs e) |
||||||
|
{ |
||||||
|
HidePreview(); |
||||||
|
e.Handled = true; |
||||||
|
|
||||||
|
var target = GetDropTarget(item, e); |
||||||
|
if (target != null) { |
||||||
|
target.Node.InternalDrop(e, target.Index); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal void HandleDragLeave(SharpTreeViewItem item, DragEventArgs e) |
||||||
|
{ |
||||||
|
HidePreview(); |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
|
||||||
|
class DropTarget |
||||||
|
{ |
||||||
|
public SharpTreeViewItem Item; |
||||||
|
public DropPlace Place; |
||||||
|
public double Y; |
||||||
|
public SharpTreeNode Node; |
||||||
|
public int Index; |
||||||
|
} |
||||||
|
|
||||||
|
DropTarget GetDropTarget(SharpTreeViewItem item, DragEventArgs e) |
||||||
|
{ |
||||||
|
var dropTargets = BuildDropTargets(item, e); |
||||||
|
var y = e.GetPosition(item).Y; |
||||||
|
foreach (var target in dropTargets) { |
||||||
|
if (target.Y >= y) { |
||||||
|
return target; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
List<DropTarget> BuildDropTargets(SharpTreeViewItem item, DragEventArgs e) |
||||||
|
{ |
||||||
|
var result = new List<DropTarget>(); |
||||||
|
var node = item.Node; |
||||||
|
|
||||||
|
if (AllowDropOrder) { |
||||||
|
TryAddDropTarget(result, item, DropPlace.Before, e); |
||||||
|
} |
||||||
|
|
||||||
|
TryAddDropTarget(result, item, DropPlace.Inside, e); |
||||||
|
|
||||||
|
if (AllowDropOrder) { |
||||||
|
if (node.IsExpanded && node.Children.Count > 0) { |
||||||
|
var firstChildItem = ItemContainerGenerator.ContainerFromItem(node.Children[0]) as SharpTreeViewItem; |
||||||
|
TryAddDropTarget(result, firstChildItem, DropPlace.Before, e); |
||||||
|
} |
||||||
|
else { |
||||||
|
TryAddDropTarget(result, item, DropPlace.After, e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var h = item.ActualHeight; |
||||||
|
var y1 = 0.2 * h; |
||||||
|
var y2 = h / 2; |
||||||
|
var y3 = h - y1; |
||||||
|
|
||||||
|
if (result.Count == 2) { |
||||||
|
if (result[0].Place == DropPlace.Inside && |
||||||
|
result[1].Place != DropPlace.Inside) { |
||||||
|
result[0].Y = y3; |
||||||
|
} |
||||||
|
else if (result[0].Place != DropPlace.Inside && |
||||||
|
result[1].Place == DropPlace.Inside) { |
||||||
|
result[0].Y = y1; |
||||||
|
} |
||||||
|
else { |
||||||
|
result[0].Y = y2; |
||||||
|
} |
||||||
|
} |
||||||
|
else if (result.Count == 3) { |
||||||
|
result[0].Y = y1; |
||||||
|
result[1].Y = y3; |
||||||
|
} |
||||||
|
if (result.Count > 0) { |
||||||
|
result[result.Count - 1].Y = h; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
void TryAddDropTarget(List<DropTarget> targets, SharpTreeViewItem item, DropPlace place, DragEventArgs e) |
||||||
|
{ |
||||||
|
SharpTreeNode node; |
||||||
|
int index; |
||||||
|
|
||||||
|
GetNodeAndIndex(item, place, out node, out index); |
||||||
|
|
||||||
|
if (node != null) { |
||||||
|
e.Effects = DragDropEffects.None; |
||||||
|
if (node.InternalCanDrop(e, index)) { |
||||||
|
DropTarget target = new DropTarget() { |
||||||
|
Item = item, |
||||||
|
Place = place, |
||||||
|
Node = node, |
||||||
|
Index = index |
||||||
|
}; |
||||||
|
targets.Add(target); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void GetNodeAndIndex(SharpTreeViewItem item, DropPlace place, out SharpTreeNode node, out int index) |
||||||
|
{ |
||||||
|
node = null; |
||||||
|
index = 0; |
||||||
|
|
||||||
|
if (place == DropPlace.Inside) { |
||||||
|
node = item.Node; |
||||||
|
index = node.Children.Count; |
||||||
|
} |
||||||
|
else if (place == DropPlace.Before) { |
||||||
|
if (item.Node.Parent != null) { |
||||||
|
node = item.Node.Parent; |
||||||
|
index = node.Children.IndexOf(item.Node); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
if (item.Node.Parent != null) { |
||||||
|
node = item.Node.Parent; |
||||||
|
index = node.Children.IndexOf(item.Node) + 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
SharpTreeNodeView previewNodeView; |
||||||
|
InsertMarker insertMarker; |
||||||
|
DropPlace previewPlace; |
||||||
|
|
||||||
|
enum DropPlace |
||||||
|
{ |
||||||
|
Before, Inside, After |
||||||
|
} |
||||||
|
|
||||||
|
void ShowPreview(SharpTreeViewItem item, DropPlace place) |
||||||
|
{ |
||||||
|
previewNodeView = item.NodeView; |
||||||
|
previewPlace = place; |
||||||
|
|
||||||
|
if (place == DropPlace.Inside) { |
||||||
|
previewNodeView.TextBackground = SystemColors.HighlightBrush; |
||||||
|
previewNodeView.Foreground = SystemColors.HighlightTextBrush; |
||||||
|
} |
||||||
|
else { |
||||||
|
if (insertMarker == null) { |
||||||
|
var adornerLayer = AdornerLayer.GetAdornerLayer(this); |
||||||
|
var adorner = new GeneralAdorner(this); |
||||||
|
insertMarker = new InsertMarker(); |
||||||
|
adorner.Child = insertMarker; |
||||||
|
adornerLayer.Add(adorner); |
||||||
|
} |
||||||
|
|
||||||
|
insertMarker.Visibility = Visibility.Visible; |
||||||
|
|
||||||
|
var p1 = previewNodeView.TransformToVisual(this).Transform(new Point()); |
||||||
|
var p = new Point(p1.X + previewNodeView.CalculateIndent() + 4.5, p1.Y - 3); |
||||||
|
|
||||||
|
if (place == DropPlace.After) { |
||||||
|
p.Y += previewNodeView.ActualHeight; |
||||||
|
} |
||||||
|
|
||||||
|
insertMarker.Margin = new Thickness(p.X, p.Y, 0, 0); |
||||||
|
|
||||||
|
SharpTreeNodeView secondNodeView = null; |
||||||
|
var index = flattener.List.IndexOf(item.Node); |
||||||
|
|
||||||
|
if (place == DropPlace.Before) { |
||||||
|
if (index > 0) { |
||||||
|
secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index - 1) as SharpTreeViewItem).NodeView; |
||||||
|
} |
||||||
|
} |
||||||
|
else if (index + 1 < flattener.List.Count) { |
||||||
|
secondNodeView = (ItemContainerGenerator.ContainerFromIndex(index + 1) as SharpTreeViewItem).NodeView; |
||||||
|
} |
||||||
|
|
||||||
|
var w = p1.X + previewNodeView.ActualWidth - p.X; |
||||||
|
|
||||||
|
if (secondNodeView != null) { |
||||||
|
var p2 = secondNodeView.TransformToVisual(this).Transform(new Point()); |
||||||
|
w = Math.Max(w, p2.X + secondNodeView.ActualWidth - p.X); |
||||||
|
} |
||||||
|
|
||||||
|
insertMarker.Width = w + 10; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void HidePreview() |
||||||
|
{ |
||||||
|
if (previewNodeView != null) { |
||||||
|
previewNodeView.ClearValue(SharpTreeNodeView.TextBackgroundProperty); |
||||||
|
previewNodeView.ClearValue(SharpTreeNodeView.ForegroundProperty); |
||||||
|
if (insertMarker != null) { |
||||||
|
insertMarker.Visibility = Visibility.Collapsed; |
||||||
|
} |
||||||
|
previewNodeView = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,190 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Diagnostics; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
public class SharpTreeViewItem : ListViewItem |
||||||
|
{ |
||||||
|
static SharpTreeViewItem() |
||||||
|
{ |
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(SharpTreeViewItem), |
||||||
|
new FrameworkPropertyMetadata(typeof(SharpTreeViewItem))); |
||||||
|
|
||||||
|
RegisterCommands(); |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeNode Node |
||||||
|
{ |
||||||
|
get { return DataContext as SharpTreeNode; } |
||||||
|
} |
||||||
|
|
||||||
|
public SharpTreeNodeView NodeView { get; internal set; } |
||||||
|
public SharpTreeView ParentTreeView { get; internal set; } |
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e) |
||||||
|
{ |
||||||
|
switch (e.Key) { |
||||||
|
case Key.F2: |
||||||
|
if (SharpTreeNode.ActiveNodes.Count == 1 && Node.IsEditable) { |
||||||
|
Node.IsEditing = true; |
||||||
|
} |
||||||
|
break; |
||||||
|
case Key.Escape: |
||||||
|
Node.IsEditing = false; |
||||||
|
break; |
||||||
|
case Key.Left: |
||||||
|
Node.IsExpanded = false; |
||||||
|
break; |
||||||
|
case Key.Right: |
||||||
|
Node.IsExpanded = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnContextMenuOpening(ContextMenuEventArgs e) |
||||||
|
{ |
||||||
|
ContextMenu = Node.GetContextMenu(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnContextMenuClosing(ContextMenuEventArgs e) |
||||||
|
{ |
||||||
|
ClearValue(ContextMenuProperty); |
||||||
|
} |
||||||
|
|
||||||
|
#region Mouse
|
||||||
|
|
||||||
|
Point startPoint; |
||||||
|
bool wasSelected; |
||||||
|
|
||||||
|
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) |
||||||
|
{ |
||||||
|
wasSelected = IsSelected; |
||||||
|
if (!IsSelected) { |
||||||
|
base.OnMouseLeftButtonDown(e); |
||||||
|
} |
||||||
|
|
||||||
|
if (Mouse.LeftButton == MouseButtonState.Pressed) { |
||||||
|
startPoint = e.GetPosition(null); |
||||||
|
CaptureMouse(); |
||||||
|
|
||||||
|
if (e.ClickCount == 2) { |
||||||
|
Node.IsExpanded = !Node.IsExpanded; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e) |
||||||
|
{ |
||||||
|
if (IsMouseCaptured) { |
||||||
|
var currentPoint = e.GetPosition(null); |
||||||
|
if (Math.Abs(currentPoint.X - startPoint.X) >= SystemParameters.MinimumHorizontalDragDistance || |
||||||
|
Math.Abs(currentPoint.Y - startPoint.Y) >= SystemParameters.MinimumVerticalDragDistance) { |
||||||
|
|
||||||
|
if (Node.InternalCanDrag()) { |
||||||
|
Node.InternalDrag(this); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) |
||||||
|
{ |
||||||
|
ReleaseMouseCapture(); |
||||||
|
if (wasSelected) { |
||||||
|
base.OnMouseLeftButtonDown(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Drag and Drop
|
||||||
|
|
||||||
|
protected override void OnDragEnter(DragEventArgs e) |
||||||
|
{ |
||||||
|
ParentTreeView.HandleDragEnter(this, e); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnDragOver(DragEventArgs e) |
||||||
|
{ |
||||||
|
ParentTreeView.HandleDragOver(this, e); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnDrop(DragEventArgs e) |
||||||
|
{ |
||||||
|
ParentTreeView.HandleDrop(this, e); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnDragLeave(DragEventArgs e) |
||||||
|
{ |
||||||
|
ParentTreeView.HandleDragLeave(this, e); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Cut / Copy / Paste / Delete Commands
|
||||||
|
|
||||||
|
static void RegisterCommands() |
||||||
|
{ |
||||||
|
CommandManager.RegisterClassCommandBinding(typeof(SharpTreeViewItem), |
||||||
|
new CommandBinding(ApplicationCommands.Cut, HandleExecuted_Cut, HandleCanExecute_Cut)); |
||||||
|
|
||||||
|
CommandManager.RegisterClassCommandBinding(typeof(SharpTreeViewItem), |
||||||
|
new CommandBinding(ApplicationCommands.Copy, HandleExecuted_Copy, HandleCanExecute_Copy)); |
||||||
|
|
||||||
|
CommandManager.RegisterClassCommandBinding(typeof(SharpTreeViewItem), |
||||||
|
new CommandBinding(ApplicationCommands.Paste, HandleExecuted_Paste, HandleCanExecute_Paste)); |
||||||
|
|
||||||
|
CommandManager.RegisterClassCommandBinding(typeof(SharpTreeViewItem), |
||||||
|
new CommandBinding(ApplicationCommands.Delete, HandleExecuted_Delete, HandleCanExecute_Delete)); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleExecuted_Cut(object sender, ExecutedRoutedEventArgs e) |
||||||
|
{ |
||||||
|
(sender as SharpTreeViewItem).Node.InternalCut(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleCanExecute_Cut(object sender, CanExecuteRoutedEventArgs e) |
||||||
|
{ |
||||||
|
e.CanExecute = (sender as SharpTreeViewItem).Node.InternalCanCut(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleExecuted_Copy(object sender, ExecutedRoutedEventArgs e) |
||||||
|
{ |
||||||
|
(sender as SharpTreeViewItem).Node.InternalCopy(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleCanExecute_Copy(object sender, CanExecuteRoutedEventArgs e) |
||||||
|
{ |
||||||
|
e.CanExecute = (sender as SharpTreeViewItem).Node.InternalCanCopy(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleExecuted_Paste(object sender, ExecutedRoutedEventArgs e) |
||||||
|
{ |
||||||
|
(sender as SharpTreeViewItem).Node.InternalPaste(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleCanExecute_Paste(object sender, CanExecuteRoutedEventArgs e) |
||||||
|
{ |
||||||
|
e.CanExecute = (sender as SharpTreeViewItem).Node.InternalCanPaste(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleExecuted_Delete(object sender, ExecutedRoutedEventArgs e) |
||||||
|
{ |
||||||
|
(sender as SharpTreeViewItem).Node.InternalDelete(); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleCanExecute_Delete(object sender, CanExecuteRoutedEventArgs e) |
||||||
|
{ |
||||||
|
e.CanExecute = (sender as SharpTreeViewItem).Node.InternalCanDelete(); |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,244 @@ |
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:Default="clr-namespace:ICSharpCode.TreeView"> |
||||||
|
|
||||||
|
<SolidColorBrush x:Key="ListBorder" |
||||||
|
Color="#FF7F9DB9" /> |
||||||
|
|
||||||
|
<Style x:Key="ExpandCollapseToggleStyle" |
||||||
|
TargetType="{x:Type ToggleButton}"> |
||||||
|
<Setter Property="Focusable" |
||||||
|
Value="False" /> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="{x:Type ToggleButton}"> |
||||||
|
<Border Width="9" |
||||||
|
Height="9" |
||||||
|
BorderThickness="1" |
||||||
|
BorderBrush="#FF7898B5" |
||||||
|
CornerRadius="1" |
||||||
|
SnapsToDevicePixels="True"> |
||||||
|
<Border.Background> |
||||||
|
<LinearGradientBrush StartPoint="0,0" |
||||||
|
EndPoint="1,1"> |
||||||
|
<LinearGradientBrush.GradientStops> |
||||||
|
<GradientStop Color="White" |
||||||
|
Offset=".2" /> |
||||||
|
<GradientStop Color="#FFC0B7A6" |
||||||
|
Offset="1" /> |
||||||
|
</LinearGradientBrush.GradientStops> |
||||||
|
</LinearGradientBrush> |
||||||
|
</Border.Background> |
||||||
|
<Path Name="ExpandPath" |
||||||
|
Margin="1,1,1,1" |
||||||
|
Fill="Black" |
||||||
|
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z" /> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger Property="IsChecked" |
||||||
|
Value="True"> |
||||||
|
<Setter Property="Data" |
||||||
|
TargetName="ExpandPath" |
||||||
|
Value="M 0 2 L 0 3 L 5 3 L 5 2 Z" /> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style TargetType="{x:Type Default:InsertMarker}"> |
||||||
|
<Setter Property="IsHitTestVisible" |
||||||
|
Value="False" /> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="{x:Type Default:InsertMarker}"> |
||||||
|
<Grid> |
||||||
|
<Border VerticalAlignment="Center" |
||||||
|
Height="2" |
||||||
|
Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" /> |
||||||
|
<Path Data="m 0 0 l 3 3 l -3 3" |
||||||
|
Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" |
||||||
|
HorizontalAlignment="Left" /> |
||||||
|
<Path Data="m 0 0 l -3 3 l 3 3" |
||||||
|
Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" |
||||||
|
HorizontalAlignment="Right" /> |
||||||
|
</Grid> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style TargetType="{x:Type Default:EditTextBox}"> |
||||||
|
<Setter Property="Foreground" |
||||||
|
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /> |
||||||
|
<Setter Property="KeyboardNavigation.TabNavigation" |
||||||
|
Value="None" /> |
||||||
|
<Setter Property="HorizontalContentAlignment" |
||||||
|
Value="Left" /> |
||||||
|
<Setter Property="FocusVisualStyle" |
||||||
|
Value="{x:Null}" /> |
||||||
|
<Setter Property="AllowDrop" |
||||||
|
Value="True" /> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="{x:Type Default:EditTextBox}"> |
||||||
|
<Border Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" |
||||||
|
BorderThickness="1" |
||||||
|
BorderBrush="{StaticResource ListBorder}" |
||||||
|
Padding="0 1 2 0"> |
||||||
|
<ScrollViewer Name="PART_ContentHost" /> |
||||||
|
</Border> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style x:Key="{x:Static Default:SharpTreeView.DefaultItemContainerStyleKey}" |
||||||
|
TargetType="{x:Type Default:SharpTreeViewItem}"> |
||||||
|
<Style.Triggers> |
||||||
|
<MultiTrigger> |
||||||
|
<MultiTrigger.Conditions> |
||||||
|
<Condition Property="ItemsControl.AlternationIndex" |
||||||
|
Value="1" /> |
||||||
|
<Condition Property="Default:SharpTreeView.ShowAlternation" |
||||||
|
Value="True" /> |
||||||
|
</MultiTrigger.Conditions> |
||||||
|
<Setter Property="Background" |
||||||
|
Value="WhiteSmoke" /> |
||||||
|
</MultiTrigger> |
||||||
|
</Style.Triggers> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style TargetType="{x:Type Default:SharpTreeViewItem}"> |
||||||
|
<Setter Property="FocusVisualStyle" |
||||||
|
Value="{x:Null}" /> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="{x:Type Default:SharpTreeViewItem}"> |
||||||
|
<Border Background="Transparent"> |
||||||
|
<Border Background="{TemplateBinding Background}"> |
||||||
|
<Default:SharpTreeNodeView Name="nodeView" |
||||||
|
HorizontalAlignment="Left" /> |
||||||
|
</Border> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger Property="IsSelected" |
||||||
|
Value="True"> |
||||||
|
<Setter TargetName="nodeView" |
||||||
|
Property="TextBackground" |
||||||
|
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" /> |
||||||
|
<Setter TargetName="nodeView" |
||||||
|
Property="Foreground" |
||||||
|
Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" /> |
||||||
|
</Trigger> |
||||||
|
<!--<MultiTrigger> |
||||||
|
<MultiTrigger.Conditions> |
||||||
|
<Condition Property="IsSelected" |
||||||
|
Value="True" /> |
||||||
|
<Condition Property="Selector.IsSelectionActive" |
||||||
|
Value="False" /> |
||||||
|
</MultiTrigger.Conditions> |
||||||
|
<Setter TargetName="nodeView" |
||||||
|
Property="TextBackground" |
||||||
|
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" /> |
||||||
|
<Setter TargetName="nodeView" |
||||||
|
Property="Foreground" |
||||||
|
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /> |
||||||
|
</MultiTrigger>--> |
||||||
|
<Trigger Property="IsEnabled" |
||||||
|
Value="False"> |
||||||
|
<Setter Property="Foreground" |
||||||
|
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" /> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style TargetType="{x:Type Default:SharpTreeNodeView}"> |
||||||
|
<Setter Property="Focusable" |
||||||
|
Value="False" /> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="{x:Type Default:SharpTreeNodeView}"> |
||||||
|
<Grid> |
||||||
|
<Default:LinesRenderer Name="linesRenderer" |
||||||
|
ClipToBounds="True" |
||||||
|
Visibility="{Binding ShowLines, RelativeSource={RelativeSource AncestorType={x:Type Default:SharpTreeView}}, Converter={Default:CollapsedWhenFalse}}" /> |
||||||
|
<StackPanel Orientation="Horizontal"> |
||||||
|
<FrameworkElement Name="spacer" /> |
||||||
|
<ToggleButton Name="expander" |
||||||
|
Style="{StaticResource ExpandCollapseToggleStyle}" |
||||||
|
IsChecked="{Binding IsExpanded}" |
||||||
|
Visibility="Hidden" |
||||||
|
Margin="0 0 6 0" |
||||||
|
VerticalAlignment="Center" /> |
||||||
|
<Border Name="checkBoxContainer" |
||||||
|
Width="16" |
||||||
|
Margin="0 0 3 0" |
||||||
|
Visibility="Collapsed"> |
||||||
|
<CheckBox IsChecked="{Binding IsChecked}" |
||||||
|
HorizontalAlignment="Center" |
||||||
|
VerticalAlignment="Center" /> |
||||||
|
</Border> |
||||||
|
<StackPanel Orientation="Horizontal" |
||||||
|
Background="Transparent" |
||||||
|
ToolTip="{Binding ToolTip}"> |
||||||
|
<ContentControl Name="icon" |
||||||
|
Content="{Binding Icon}" |
||||||
|
Width="16" |
||||||
|
Height="16" |
||||||
|
Margin="0 0 5 1" |
||||||
|
VerticalAlignment="Center" |
||||||
|
Focusable="False" /> |
||||||
|
<Border Name="textContainer" |
||||||
|
Background="{TemplateBinding TextBackground}"> |
||||||
|
<ContentControl Content="{Binding Text}" |
||||||
|
Margin="2 0 6 0" |
||||||
|
VerticalAlignment="Center" |
||||||
|
Focusable="False" /> |
||||||
|
</Border> |
||||||
|
<Border Name="textEditorContainer" /> |
||||||
|
</StackPanel> |
||||||
|
</StackPanel> |
||||||
|
</Grid> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<DataTrigger Binding="{Binding IsEditing}" |
||||||
|
Value="True"> |
||||||
|
<Setter TargetName="textContainer" |
||||||
|
Property="Visibility" |
||||||
|
Value="Collapsed" /> |
||||||
|
</DataTrigger> |
||||||
|
<DataTrigger Binding="{Binding IsExpanded}" |
||||||
|
Value="True"> |
||||||
|
<Setter TargetName="icon" |
||||||
|
Property="Content" |
||||||
|
Value="{Binding ExpandedIcon}" /> |
||||||
|
</DataTrigger> |
||||||
|
<DataTrigger Binding="{Binding ShowExpander}" |
||||||
|
Value="True"> |
||||||
|
<Setter TargetName="expander" |
||||||
|
Property="Visibility" |
||||||
|
Value="Visible" /> |
||||||
|
</DataTrigger> |
||||||
|
<DataTrigger Binding="{Binding IsCheckable}" |
||||||
|
Value="True"> |
||||||
|
<Setter TargetName="checkBoxContainer" |
||||||
|
Property="Visibility" |
||||||
|
Value="Visible" /> |
||||||
|
</DataTrigger> |
||||||
|
<DataTrigger Binding="{Binding IsCut}" |
||||||
|
Value="True"> |
||||||
|
<Setter TargetName="icon" |
||||||
|
Property="Opacity" |
||||||
|
Value="0.5" /> |
||||||
|
</DataTrigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
</ResourceDictionary> |
@ -0,0 +1,147 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.Collections.Specialized; |
||||||
|
|
||||||
|
namespace ICSharpCode.TreeView |
||||||
|
{ |
||||||
|
class TreeFlattener |
||||||
|
{ |
||||||
|
public TreeFlattener(SharpTreeNode root, bool includeRoot) |
||||||
|
{ |
||||||
|
this.root = root; |
||||||
|
this.includeRoot = includeRoot; |
||||||
|
List = new ObservableCollection<SharpTreeNode>(); |
||||||
|
} |
||||||
|
|
||||||
|
SharpTreeNode root; |
||||||
|
bool includeRoot; |
||||||
|
|
||||||
|
public ObservableCollection<SharpTreeNode> List { get; private set; } |
||||||
|
|
||||||
|
public void Start() |
||||||
|
{ |
||||||
|
if (includeRoot) { |
||||||
|
Add(root); |
||||||
|
} |
||||||
|
else { |
||||||
|
root.Children.CollectionChanged += node_ChildrenChanged; |
||||||
|
} |
||||||
|
|
||||||
|
foreach (var node in root.ExpandedDescendants()) { |
||||||
|
Add(node); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void Stop() |
||||||
|
{ |
||||||
|
while (List.Count > 0) { |
||||||
|
RemoveAt(0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Add(SharpTreeNode node) |
||||||
|
{ |
||||||
|
Insert(List.Count, node); |
||||||
|
} |
||||||
|
|
||||||
|
void Insert(int index, SharpTreeNode node) |
||||||
|
{ |
||||||
|
List.Insert(index, node); |
||||||
|
node.PropertyChanged += node_PropertyChanged; |
||||||
|
if (node.IsExpanded) { |
||||||
|
node.Children.CollectionChanged += node_ChildrenChanged; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void RemoveAt(int index) |
||||||
|
{ |
||||||
|
var node = List[index]; |
||||||
|
List.RemoveAt(index); |
||||||
|
node.PropertyChanged -= node_PropertyChanged; |
||||||
|
if (node.IsExpanded) { |
||||||
|
node.Children.CollectionChanged -= node_ChildrenChanged; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ClearDescendants(SharpTreeNode node) |
||||||
|
{ |
||||||
|
var index = List.IndexOf(node); |
||||||
|
while (index + 1 < List.Count && List[index + 1].Level > node.Level) { |
||||||
|
RemoveAt(index + 1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void node_PropertyChanged(object sender, PropertyChangedEventArgs e) |
||||||
|
{ |
||||||
|
if (e.PropertyName == "IsExpanded") { |
||||||
|
var node = sender as SharpTreeNode; |
||||||
|
|
||||||
|
if (node.IsExpanded) { |
||||||
|
var index = List.IndexOf(node); |
||||||
|
foreach (var childNode in node.ExpandedDescendants()) { |
||||||
|
Insert(++index, childNode); |
||||||
|
} |
||||||
|
node.Children.CollectionChanged += node_ChildrenChanged; |
||||||
|
} |
||||||
|
else { |
||||||
|
ClearDescendants(node); |
||||||
|
node.Children.CollectionChanged -= node_ChildrenChanged; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Insert(SharpTreeNode parent, int index, SharpTreeNode node) |
||||||
|
{ |
||||||
|
int finalIndex = 0; |
||||||
|
if (index > 0) { |
||||||
|
finalIndex = List.IndexOf(parent.Children[index - 1]) + 1; |
||||||
|
while (finalIndex < List.Count && List[finalIndex].Level > node.Level) { |
||||||
|
finalIndex++; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
finalIndex = List.IndexOf(parent) + 1; |
||||||
|
} |
||||||
|
Insert(finalIndex, node); |
||||||
|
} |
||||||
|
|
||||||
|
void RemoveAt(SharpTreeNode parent, int index, SharpTreeNode node) |
||||||
|
{ |
||||||
|
var i = List.IndexOf(node); |
||||||
|
foreach (var child in node.ExpandedDescendantsAndSelf()) { |
||||||
|
RemoveAt(i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void node_ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||||
|
{ |
||||||
|
var collection = sender as SharpTreeNodeCollection; |
||||||
|
var parent = collection.Parent; |
||||||
|
var index = List.IndexOf(collection.Parent) + 1; |
||||||
|
|
||||||
|
switch (e.Action) { |
||||||
|
case NotifyCollectionChangedAction.Add: |
||||||
|
Insert(parent, e.NewStartingIndex, e.NewItems[0] as SharpTreeNode); |
||||||
|
break; |
||||||
|
case NotifyCollectionChangedAction.Remove: |
||||||
|
RemoveAt(parent, e.OldStartingIndex, e.OldItems[0] as SharpTreeNode); |
||||||
|
break; |
||||||
|
case NotifyCollectionChangedAction.Move: |
||||||
|
RemoveAt(parent, e.OldStartingIndex, e.OldItems[0] as SharpTreeNode); |
||||||
|
Insert(parent, e.NewStartingIndex, e.NewItems[0] as SharpTreeNode); |
||||||
|
break; |
||||||
|
case NotifyCollectionChangedAction.Replace: |
||||||
|
RemoveAt(parent, e.OldStartingIndex, e.OldItems[0] as SharpTreeNode); |
||||||
|
Insert(parent, e.NewStartingIndex, e.NewItems[0] as SharpTreeNode); |
||||||
|
break; |
||||||
|
case NotifyCollectionChangedAction.Reset: |
||||||
|
ClearDescendants(parent); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00 |
||||||
|
# Visual Studio 2008 |
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView", "ICSharpCode.TreeView\ICSharpCode.TreeView.csproj", "{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}" |
||||||
|
EndProject |
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TreeView.Demo", "ICSharpCode.TreeView.Demo\ICSharpCode.TreeView.Demo.csproj", "{B521D667-3613-429C-AB58-26A5B5A82004}" |
||||||
|
EndProject |
||||||
|
Global |
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||||
|
Debug|Any CPU = Debug|Any CPU |
||||||
|
Release|Any CPU = Release|Any CPU |
||||||
|
EndGlobalSection |
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||||
|
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||||
|
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||||
|
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||||
|
{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}.Release|Any CPU.Build.0 = Release|Any CPU |
||||||
|
{B521D667-3613-429C-AB58-26A5B5A82004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||||
|
{B521D667-3613-429C-AB58-26A5B5A82004}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||||
|
{B521D667-3613-429C-AB58-26A5B5A82004}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||||
|
{B521D667-3613-429C-AB58-26A5B5A82004}.Release|Any CPU.Build.0 = Release|Any CPU |
||||||
|
EndGlobalSection |
||||||
|
GlobalSection(SolutionProperties) = preSolution |
||||||
|
HideSolutionNode = FALSE |
||||||
|
EndGlobalSection |
||||||
|
EndGlobal |
Loading…
Reference in new issue