最近又开始跟WPF打交道,项目里面用到了TreeView这个控件。然后需要有一个连线的外观就像是这样

二话不说,百度了一下,找到一个实现, 通道

把代码拷贝到项目里面,跑了一下,看上去还不错。但是这哥们的实现里面有一个缺陷。我们可以看到每个节点的最后的子节点前面的竖线,绘制方式跟其他的节点是有区别的,跟上图显示的一样。

拷贝的代码,在树中添加新的节点的时候,之前最后节点的"|_"这种风格的线在新节点插入后不会动态更新,还是会保持这种风格。这种风格在不需要改变节点的时候还是可以的,而需要增删节点的话,那么  就不合适了。

继续在网上找了找没有现成的解决方案,后来想了一下,可以试试在给一个节点添加子节点的时候,将所有子节点都删除然后再重新添加进去这种方式来更新UI。但我没去尝试这个方案是否真的可以。额,不管是否可行,我都不太喜欢这个方案,所以就只能自己做了。

那么从这里开始描述整个实现过程。


首先是问题的根源,一组节点的最后一个节点前面的竖线的绘制方式是需要区别于其他的节点。然后这个是由于它的位置所决定的,而跟它本身的属性是没有一点关系的,我们也没有什么直接的方式来得到这个信息,能做的无非就像上面那个哥们那样,去跑一遍index之类的方法来判定是否是最后一个节点。

根据这个逻辑,我们可以发现,单单处理TreeViewItem这个类的Style是没有用的,或者说是有缺陷的。

那么怎么办呢?

TreeViewItem本身是ItemsControl,TreeView本身也是,那么它的绘制方式就很明显了,无非是ItemsTemplate决定了Item的数据外观,ItemsPanel决定了如何去组织Items。

我们要做的就是在绘制Items的时候,把竖线放到里面就行了,这样我们就有了竖线,而且我们在遍历的时候是知道每个节点的位置信息的,这样最后一个节点的绘制信息我们是能拿到的。

横线的话,我们有两个选择,一个是也在ItemsPanel里面去绘制;或者我们把这根线放到TreeViewItem的Style里面。我选择了后者,原因是,我们的“+”是在TreeViewItem里面的。而“+”在横线的前面。

ItemsPanel的话,我们重写一下StackPanel就足够了。

这样方案基本就确定了:

1. 重写StackPanel来绘制Item前面的竖线

2. 重写TreeViewItem的Style来绘制“+-”号和横线

首先们准备数据模型,来调试UI

public class ItemViewModel
{
public string Name { get; set; }
public IList<ItemViewModel> Children { get; set; }
}

TreeView的基本设置

<TreeView x:Name="treeView">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

TreeView和TreeViewItem的默认模板,直接从msdn拷贝,通道

只需要在OnRender方法里面在绘制Item的时候在前面画一根线就行了,主要是处理一下最后一个节点前的线,只绘制1/2即可。但这么算的话,会有一个问题,如果节点自己有子节点的话,那么子节点的高度是会算在当前节点的,这样一来竖线的高度是错的,我做了一个设定,就是在子节点的内容没有换行的情况下,所有的子节点的高度都是一样的(实际上,基本情况也就是这样)。这样一来:1. 没有子节点那么就是1/2的子节点高度;如果有那么就是RenderSize.Height / Items.Count / 2这种。

protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (Children.Count > )
{
TreeViewItem child;
Point point;
Pen pen = new Pen(LineBrush, LineThiness);
Point startPoint = new Point(Offset,), endPoint = new Point(Offset,);
for (int i = ; i < Children.Count - ; i++)
{
child = Children[i] as TreeViewItem;
point = child.TranslatePoint(new Point(), this);
startPoint.Y = point.Y;
endPoint.Y = point.Y + child.RenderSize.Height;
dc.DrawLine(pen, startPoint, endPoint);
}
child = Children[Children.Count - ] as TreeViewItem;
point = child.TranslatePoint(new Point(), this);
startPoint.Y = point.Y;
if (!child.IsExpanded || child.Items == null || child.Items.Count < )
endPoint.Y = point.Y + child.RenderSize.Height / ;
else
endPoint.Y = point.Y + child.RenderSize.Height / child.Items.Count / ;
dc.DrawLine(pen, startPoint, endPoint);
}
}

然后再新建一个TreeViewItem的Style,里面画个“+” "-"号再加一根横线就好了

        <Style x:Key="customToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid Background="White">
<Rectangle Fill="{x:Null}" Stroke="Black" StrokeThickness="1"/>
<Rectangle Height="1" Fill="Black" VerticalAlignment="Center" />
<Rectangle Width="1" Fill="Black" HorizontalAlignment="Center" x:Name="line" Visibility="Collapsed"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Visibility" Value="Visible" TargetName="line"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

设置一下TreeViewItem中的ItemsPanel引用我们定义的Panel,就可以了,当然还有一些细节要处理,不过我就不细说了,我已经没耐心说下去了,所有的代码都在下面,写这篇文章主要是想写了,嗯,就是这样。

<Window x:Class="TreeViewStyleDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TreeViewStyleDemo"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>
<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>
<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>
<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>
<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>
<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>
<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
<LinearGradientBrush x:Key="MenuPopupBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{DynamicResource ControlLightColor}" Offset="0" />
<GradientStop Color="{DynamicResource ControlMediumColor}" Offset="0.5" />
<GradientStop Color="{DynamicResource ControlLightColor}" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill" StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#000000FF" Offset="0" />
<GradientStop Color="#600000FF" Offset="0.4" />
<GradientStop Color="#600000FF" Offset="0.6" />
<GradientStop Color="#000000FF" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Style x:Key="{x:Type TreeView}" TargetType="TreeView">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeView">
<Border Name="Border" CornerRadius="1" BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}" />
</Border.Background>
<ScrollViewer Focusable="False" CanContentScroll="False" Padding="4">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Width="15" Height="13" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Collapsed">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Expanded">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="Collapsed" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1,1,1,1" Data="M 4 0 L 8 4 L 4 8 Z">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Fill>
</Path>
<Path x:Name="Expanded" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1,1,1,1" Data="M 0 4 L 8 4 L 4 8 Z" Visibility="Hidden">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource GlyphColor}" />
</Path.Fill>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="customToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid Background="White">
<Rectangle Fill="{x:Null}" Stroke="Black" StrokeThickness="1"/>
<Rectangle Height="1" Fill="Black" VerticalAlignment="Center" />
<Rectangle Width="1" Fill="Black" HorizontalAlignment="Center" x:Name="line" Visibility="Collapsed"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Visibility" Value="Visible" TargetName="line"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TreeViewItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="0,0,0,0" StrokeThickness="5" Stroke="Black" StrokeDashArray="1 2" Opacity="0" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Padding" Value="1,0,0,0" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<local:CustomPanel LineBrush ="Black" Background="LightYellow" SnapsToDevicePixels="True" Orientation="Vertical" LineThiness=".5" Offset="9.5" IsItemsHost="True"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19" Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd" Storyboard.TargetProperty="(Panel.Background). (SolidColorBrush.Color)" >
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource SelectedBackgroundColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unselected" />
<VisualState x:Name="SelectedInactive">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd" Storyboard.TargetProperty="(Panel.Background). (SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="{StaticResource SelectedUnfocusedColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ExpansionStates">
<VisualState x:Name="Expanded">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ItemsHost">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Height="1" Fill="Black" VerticalAlignment="Center" Margin="9 0 0 0"/>
<ToggleButton Width="9" Height="9" x:Name="Expander" Style="{StaticResource customToggleButtonStyle}" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
<Border x:Name="Bd" Grid.Column="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="Expander" Property="Visibility" Value="Hidden" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader" Value="false" />
<Condition Property="Width" Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header" Property="MinWidth" Value="75" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader" Value="false" />
<Condition Property="Height" Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header" Property="MinHeight" Value="19" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TreeView x:Name="treeView">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<Button VerticalAlignment="Bottom" Click="Button_Click" Content="Click"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 TreeViewStyleDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); for (int i = ; i < ; i++)
{
var item = new ItemViewModel();
item.Name = "Item" + i;
item.Children = new ObservableCollection<ItemViewModel>();
for (int j = ; j < ; j++)
{
var sub_item = new ItemViewModel(){ Name = "SubItem" + j};
sub_item.Children = new ObservableCollection<ItemViewModel>();
for (int k = ; k < ; k++)
{
sub_item.Children.Add(new ItemViewModel() { Name = "SubsubItem" + k });
}
item.Children.Add(sub_item);
}
items.Add(item);
} treeView.ItemsSource = items;
} ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>(); private void Button_Click(object sender, RoutedEventArgs e)
{
items[].Children.Add(new ItemViewModel() { Name = "Added" });
}
} public class ItemViewModel
{
public string Name { get; set; }
public IList<ItemViewModel> Children { get; set; }
} public class CustomPanel : StackPanel
{
protected override Size ArrangeOverride(Size arrangeSize)
{
return base.ArrangeOverride(arrangeSize);
} protected override Size MeasureOverride(Size constraint)
{
return base.MeasureOverride(constraint);
} protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (Children.Count > )
{
TreeViewItem child;
Point point;
Pen pen = new Pen(LineBrush, LineThiness);
Point startPoint = new Point(Offset,), endPoint = new Point(Offset,);
for (int i = ; i < Children.Count - ; i++)
{
child = Children[i] as TreeViewItem;
point = child.TranslatePoint(new Point(), this);
startPoint.Y = point.Y;
endPoint.Y = point.Y + child.RenderSize.Height;
dc.DrawLine(pen, startPoint, endPoint);
}
child = Children[Children.Count - ] as TreeViewItem;
point = child.TranslatePoint(new Point(), this);
startPoint.Y = point.Y;
if (!child.IsExpanded || child.Items == null || child.Items.Count < )
endPoint.Y = point.Y + child.RenderSize.Height / ;
else
endPoint.Y = point.Y + child.RenderSize.Height / child.Items.Count / ;
dc.DrawLine(pen, startPoint, endPoint);
}
} public Brush LineBrush
{
get { return (Brush)GetValue(LineBrushProperty); }
set { SetValue(LineBrushProperty, value); }
} public static readonly DependencyProperty LineBrushProperty =
DependencyProperty.Register("LineBrush", typeof(Brush), typeof(CustomPanel), new PropertyMetadata(null)); public double LineThiness
{
get { return (double)GetValue(LineThinessProperty); }
set { SetValue(LineThinessProperty, value); }
} public static readonly DependencyProperty LineThinessProperty = DependencyProperty.Register("LineThiness", typeof(double), typeof(CustomPanel), new PropertyMetadata(0d, new PropertyChangedCallback((o,e)=>{(o as Panel).InvalidateVisual(); }))); public double Offset
{
get { return (double)GetValue(OffsetProperty); }
set { SetValue(OffsetProperty, value); }
}
public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register("Offset", typeof(double), typeof(CustomPanel), new PropertyMetadata(0d, new PropertyChangedCallback((o,e)=>{ (o as Panel).InvalidateVisual(); }))); }
}

好,收工


这里已经发现了一个坑,多级节点的高度计算上会有问题,果然应该用固定的行高来计算才是靠谱的么,自己根据需要改吧,我懒得弄了。

WPF中TreeView的+-号和连线style的一种实现的更多相关文章

  1. WPF中TreeView.BringIntoView方法的替代方案

    原文:WPF中TreeView.BringIntoView方法的替代方案 WPF中TreeView.BringIntoView方法的替代方案 周银辉 WPF中TreeView.BringIntoVie ...

  2. WPF中使用amCharts绘制股票K线图

    原文:WPF中使用amCharts绘制股票K线图 本想自己用GDI绘图, 通过数据直接绘制一张蜡柱图, 但觉得这样子的功能比较少, 所以到网上搜索一些能画出K线图的控件. 发现DynamicDataD ...

  3. VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法

    原文:VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/det ...

  4. WPF中TreeView的使用

    因为项目中需要用到TreeView控件,由于是第一次在WPF中用到,因此事先在网上搜了很多关于数据绑定的方法介绍,个人经过实际应用,觉得WPF中的HierarchicalDataTemplate定义模 ...

  5. WPF中TreeView控件的使用案例

    WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...

  6. WPF中TreeView单击展开其子元素以及点击一个元素展开其他元素收起

    TreeView单击展开其子元素: 在WPF的TreeView控件中,要想展开它的子元素,我们必须要鼠标左键点两下或者右键点一下,那么我们怎样实现左键点一下就使它展开呢? Xaml: <Grid ...

  7. WPF中TreeView控件SelectedItemChanged方法的MVVM绑定

    问题描述:左侧treeview控件中点击不同类别的节点时,右侧的页面会显示不同的权限.比如对于My Publications,拥有Modify和Delete两种权限,对于My Subscription ...

  8. WPF中TreeView控件数据绑定和后台动态添加数据(二)

    写在前面:在(一)中,介绍了TreeView控件MVVM模式下数据绑定的方法.在这篇文章中,将总结给节点添加事件的方法,这样说有些不对,总之实现的效果就是点击某个节点,将出现对应于该节点的页面或者数据 ...

  9. WPF中TreeView控件数据绑定和后台动态添加数据(一)

    数据绑定: 更新内容:补充在MVVM模式上的TreeView控件数据绑定的代码. xaml代码: <TreeView Name="syntaxTree" ItemsSourc ...

随机推荐

  1. PHP响应码和HTTP请求方法

    HTTP请求报文由请求行(request line).请求头部(header).空行和请求数据4个部分组成,格式如下 可见请求行由请求方法字段.URL字段和HTTP协议版本字段3个字段组成,它们用空格 ...

  2. 一个判断I2C总线通信异常原因的方法

    此问题由某客户提出,应用处理器 AP与 MCU进行 I2C通信,通信会经常发生异常,需要定位原因. 首先需要定位的是因为哪个器件发的波形不正确导致通信异常,所以我们在 I2C 线路上增加了以下处理,增 ...

  3. 关于php利用数组中某个字段进行排序

    工作中用到了一个相关的问题,搜索了百度有好多种方法,但是不同方法对应的函数不同,试了几个发现还是下面这个比较好用: array_multisort($sortarray,SortRank,$sortl ...

  4. iptables随笔

    iptables 分为四表五链 四表: filter表 nat 表 mangle 表 raw 表 五链 INPUT 链 OUTPUT 链 FORWARD 链 PREROUTING(路由前) POSTR ...

  5. js 一些兼容检测

    1. IE5.0之前不支持 document.getElementById(),但存在 document.all[] function getElementById(id) { if(document ...

  6. extJs学习的资源

    http://www.qeefee.com/zt-extjs   Ext JS 6 入门学习资料大全(2016-12-14)   cddnExtJS学习:http://blog.csdn.net/co ...

  7. select2插件设置选中值并显示的问题

    在select2中,要想设置指定值为选中状态并显示: $("#select2_Id").val("XXXXX").select2() 或者 var obj= $ ...

  8. JAVA中字符串操作几种方式对比

    @参考文章 方法及原理: 方法1:a=a+b实际上另开辟一个空间c=a+b;然后将c的引用赋给a 方法2:a += b实际上是建立一个StringBuffer,然后调用append(),最后再将Str ...

  9. 516. Longest Palindromic Subsequence最长的不连续回文串的长度

    [抄题]: Given a string s, find the longest palindromic subsequence's length in s. You may assume that ...

  10. ipv6 docker

    DOCKER, IPV6 BASIC CONFIGURATION OF DOCKER ENGINE WITH IPV6 SEPTEMBER 21, 2015 EYEPV6(AT)GMAIL(DOT)C ...