WPF中TreeView的+-号和连线style的一种实现
最近又开始跟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的一种实现的更多相关文章
- WPF中TreeView.BringIntoView方法的替代方案
原文:WPF中TreeView.BringIntoView方法的替代方案 WPF中TreeView.BringIntoView方法的替代方案 周银辉 WPF中TreeView.BringIntoVie ...
- WPF中使用amCharts绘制股票K线图
原文:WPF中使用amCharts绘制股票K线图 本想自己用GDI绘图, 通过数据直接绘制一张蜡柱图, 但觉得这样子的功能比较少, 所以到网上搜索一些能画出K线图的控件. 发现DynamicDataD ...
- VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法
原文:VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/det ...
- WPF中TreeView的使用
因为项目中需要用到TreeView控件,由于是第一次在WPF中用到,因此事先在网上搜了很多关于数据绑定的方法介绍,个人经过实际应用,觉得WPF中的HierarchicalDataTemplate定义模 ...
- WPF中TreeView控件的使用案例
WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...
- WPF中TreeView单击展开其子元素以及点击一个元素展开其他元素收起
TreeView单击展开其子元素: 在WPF的TreeView控件中,要想展开它的子元素,我们必须要鼠标左键点两下或者右键点一下,那么我们怎样实现左键点一下就使它展开呢? Xaml: <Grid ...
- WPF中TreeView控件SelectedItemChanged方法的MVVM绑定
问题描述:左侧treeview控件中点击不同类别的节点时,右侧的页面会显示不同的权限.比如对于My Publications,拥有Modify和Delete两种权限,对于My Subscription ...
- WPF中TreeView控件数据绑定和后台动态添加数据(二)
写在前面:在(一)中,介绍了TreeView控件MVVM模式下数据绑定的方法.在这篇文章中,将总结给节点添加事件的方法,这样说有些不对,总之实现的效果就是点击某个节点,将出现对应于该节点的页面或者数据 ...
- WPF中TreeView控件数据绑定和后台动态添加数据(一)
数据绑定: 更新内容:补充在MVVM模式上的TreeView控件数据绑定的代码. xaml代码: <TreeView Name="syntaxTree" ItemsSourc ...
随机推荐
- 两个时间点计算相隔几年,几个月,几天-java
本文采用Calendar 实现 ,当然也可以用java8提供的愉快且方便的时间处理- LocalDate import java.text.ParseException; import java.te ...
- 4-29 c语言之栈,队列,双向链表
今天学习了数据结构中栈,队列的知识 相对于单链表来说,栈和队列就是添加的方式不同,队列就相当于排队,先排队的先出来(FIFO),而栈就相当于弹夹,先压进去的子弹后出来(FILO). 首先看一下栈(St ...
- JEECG 上传插件升级-代码生成器
前言: 现有的uploadify上传是基于swf的,随着H5的普及,flash即将退出历史舞台,JEECG本着与时俱进的原则,将全面升级JEECG系统中的上传功能,采用新式上传插件plupload,此 ...
- python 优先队列
python 优先队列 from queue import PriorityQueue q = PriorityQueue() q.put((2, 'code')) q.put((1, 'eat')) ...
- 2018 pycharm最近激活码
今天更新了一下pycharm,结果之前的激活就不能用了,下面是新的激活方法: 1.mac下在终端进入etc目录: cd /etc 2.编辑hosts文件: vi hosts 将“0.0.0.0 acc ...
- PhoenixFD插件流体模拟——UI布局【Resimulation】详解
Liquid Resimulation 流体再(重)渲染 本文主要讲解Resimulation折叠栏中的内容 主要内容 Overview 综述 Parameters 参数 综述 Liquid Resi ...
- 利用JS自动打开页面上链接的实现代码
在这里做一下简单记录,防止自己忘记. 下面是实现自动点击打开链接的主要函数,功能不再细说,防止太多人滥用,有心的人一看就会明白,改把改把就是一个邪恶的程序: function randopen() { ...
- POJ-2533.Longest Ordered Subsequence (LIS模版题)
本题大意:和LIS一样 本题思路:用dp[ i ]保存前 i 个数中的最长递增序列的长度,则可以得出状态转移方程dp[ i ] = max(dp[ j ] + 1)(j < i) 参考代码: # ...
- react项目请求数据的fetch的使用
准备三个文件(封装请求函数),然后测试一下,能不能调用数据 第一个文件 request.js import 'whatwg-fetch'; /** * Parses the JSON returne ...
- Linux下Mysql安装(RPM安装)
1. 首先检查机器里是否已经存在MySQL $ rpm -qa | grep mysql 2. 去官网下载相应的rpm包:https://dev.mysql.com/downloads/mysql/ ...