记一次自定义基因分类图实现(二)
前言
最近,心情略差,各种烦心事。总是提不起力气写点啥,但是上周写了一,这周还是把二写了吧,内容没那么多,但是总是自己的一些分享,记录。总得有个宣泄口~,发现不打游戏了,之后 的确没有什么好的爱好能够吸引我的注意力,这几年满脑子都是搞钱两个字,入迷了!
正文
上期讲了怎么实现分类关系,下一步就是实现中间扩展,首先两个需求,需要横向纵向无限扩展,第二点,需要跟随列宽,同步到中心数据。
思路:
用两个ItemsControl来表示横向列名和纵向列名,中间部分用两个itemsControl来生成数据主内容,因为策略要保证中间部分宽度 跟顶部宽度一致,所以中间数据表线竖后横。灵魂画手
所以我们准备一个这样的数据结构,作为中间基类
代码语言:csharp复制 public class BaseClusterModel
{
/// <summary>
/// 级别
/// </summary>
public int Level { get; set; }
/// <summary>
/// 每个元素宽度
/// </summary>
internal double Width { get; set; }
/// <summary>
/// 每个元素高度
/// </summary>
internal double Height { get; set; }
/// <summary>
/// 父级唯一标识
/// </summary>
public string ParentUid { get; set; }
/// <summary>
/// 标识
/// </summary>
public string Uid { get; set; }
}
基于基类demo,做了一次扩展,扩展中间类为,
代码语言:csharp复制 public class TestCluster : BaseClusterModel, INotifyPropertyChanged
{
private double showHeight;
private double showWidth;
public double ShowWidth
{
get => showWidth;
set
{
showWidth = value;
RaiseOnPropertyChanged();
}
}
public double ShowHeight
{
get => showHeight;
set
{
showHeight = value;
RaiseOnPropertyChanged();
}
}
public string Name { get; set; }
public List<TestCluster> Children { get; set; } = new List<TestCluster>();
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseOnPropertyChanged([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
通过ShowWidth和来同步宽度,可以通过behavior实现宽度变化绑定
代码语言:csharp复制 public class NoticeSizeChangedBehavior : Behavior<UIElement>
{
protected override void OnAttached()
{
base.OnAttached();
var element = (AssociatedObject as FrameworkElement);
if (element != null)
element.SizeChanged += Element_SizeChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
var element = (AssociatedObject as FrameworkElement);
if (element != null)
element.SizeChanged -= Element_SizeChanged;
}
// Using a DependencyProperty as the backing store for OvservedWidth. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OvservedWidthProperty =
DependencyProperty.Register("OvservedWidth", typeof(double), typeof(NoticeSizeChangedBehavior), new PropertyMetadata(0d));
public static readonly DependencyProperty OvseredHeightProperty =
DependencyProperty.Register("OvseredHeight", typeof(double), typeof(NoticeSizeChangedBehavior), new PropertyMetadata(0d));
public double OvseredHeight
{
get { return (double)GetValue(OvseredHeightProperty); }
set { SetValue(OvseredHeightProperty, value); }
}
public double OvservedWidth
{
get { return (double)GetValue(OvservedWidthProperty); }
set { SetValue(OvservedWidthProperty, value); }
}
private void Element_SizeChanged(object sender, SizeChangedEventArgs e)
{
OvservedWidth = (sender as FrameworkElement).ActualWidth;
OvseredHeight = (sender as FrameworkElement).ActualHeight;
}
}
这样我们就可以保证变化了。
现在我们还有一个问题,怎么在主内容滚动相应方向的,另一个方向的标题冻结。
我们可以通过两个ScrollBar和绑定来实现,看效果,
这样我们基本就实现完成了,最后总布局代码贴上
代码语言:xml复制 <Window x:Class="ClusteringPlot.MainWindow"
xmlns=";
xmlns:x=";
xmlns:d=";
xmlns:mc=";
xmlns:local="clr-namespace:ClusteringPlot"
xmlns:series="clr-namespace:EasyPlot.Series;assembly=EasyPlot"
xmlns:behavior="clr-namespace:EasyPlot.Behaviors;assembly=EasyPlot"
xmlns:i="; xmlns:converters="clr-namespace:ClusteringPlot.Converters"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<converters:ScrollValueConverter x:Key="ScrollValueConverter"></converters:ScrollValueConverter>
<converters:ScrollBarMaximumConverter x:Key="ScrollBarMaximumConverter"></converters:ScrollBarMaximumConverter>
<converters:ScrollBarVisibilityConverter x:Key="ScrollBarVisibilityConverter"></converters:ScrollBarVisibilityConverter>
</Window.Resources>
<Grid Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.2*"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Grid.Column="1" Margin="0,0,0,0" x:Name="paramBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ClipToBounds="True">
<Canvas >
<ItemsControl x:Name="root1" Height="{Binding Path=ActualHeight,ElementName=paramBorder}" Grid.Column="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<series:ClusterPanel MaxLevel="3" Orientation="Horizontal"></series:ClusterPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="Green" MinWidth="50" MinHeight="20" Margin="5">
<i:Interaction.Behaviors>
<behavior:NoticeSizeChangedBehavior OvservedWidth="{Binding ShowWidth, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
<TextBlock Foreground="White" Text="{Binding Name}"></TextBlock>
<TextBlock Foreground="White" Text="{Binding Level}"></TextBlock>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.RenderTransform>
<TranslateTransform X="{Binding ElementName=HorizontalBar,Path=Value, Converter={StaticResource ScrollValueConverter}}" />
</ItemsControl.RenderTransform>
</ItemsControl>
</Canvas>
</Border>
<Border Grid.Column="0" Grid.Row="1" Margin="0,0,0,0" x:Name="verBorder" VerticalAlignment="Stretch" ClipToBounds="True">
<Canvas >
<ItemsControl x:Name="root" Grid.Row="1" Width="{Binding Path=ActualWidth,ElementName=verBorder}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<series:ClusterPanel MaxLevel="3" Orientation="Vertical"></series:ClusterPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="Green" MinWidth="50" MinHeight="20" Margin="5">
<i:Interaction.Behaviors>
<behavior:NoticeSizeChangedBehavior OvseredHeight="{Binding ShowHeight, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
<TextBlock Foreground="White" Text="{Binding Name}"></TextBlock>
<TextBlock Foreground="White" Text="{Binding Level}"></TextBlock>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.RenderTransform>
<TranslateTransform Y="{Binding ElementName=VerticalBar,Path=Value, Converter={StaticResource ScrollValueConverter}}" />
</ItemsControl.RenderTransform>
</ItemsControl>
</Canvas>
</Border>
<Border x:Name="ContentBorder" Grid.Column="1" Grid.Row="1" Margin="0,0,0,0" BorderThickness="0,0,0,0" BorderBrush="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ClipToBounds="True">
<Canvas >
<ItemsControl Grid.Column="1" Grid.Row="1" x:Name="ContentItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Children}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="Yellow" MinWidth="50" MinHeight="20" Margin="5" Width="{Binding DataContext.ShowWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl},Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" Height="20">
<TextBlock Text="{Binding Name}"></TextBlock>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.RenderTransform>
<TranslateTransform X="{Binding ElementName=HorizontalBar,Path=Value, Converter={StaticResource ScrollValueConverter}}"
Y="{Binding ElementName=VerticalBar,Path=Value, Converter={StaticResource ScrollValueConverter}}" />
</ItemsControl.RenderTransform>
</ItemsControl>
</Canvas>
</Border>
<!--主内容横向滚动-->
<ScrollBar x:Name="HorizontalBar" Opacity="0.5" Grid.Row="1" Grid.Column="1"
Background="Transparent"
Orientation="Horizontal"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
ViewportSize="{Binding ElementName=ContentBorder, Path=ActualWidth}"
Minimum="0.0"
Value="0"
Margin="0,0,0,0"
Cursor="Arrow"
>
<ScrollBar.Maximum>
<MultiBinding Mode="OneWay" Converter="{StaticResource ScrollBarMaximumConverter}">
<MultiBinding.Bindings>
<Binding ElementName="ContentBorder" Path="ActualWidth" />
<Binding ElementName="ContentItemsControl" Path="ActualWidth" />
</MultiBinding.Bindings>
</MultiBinding>
</ScrollBar.Maximum>
<ScrollBar.Visibility>
<MultiBinding Mode="OneWay" Converter="{StaticResource ScrollBarVisibilityConverter}">
<MultiBinding.Bindings>
<Binding ElementName="ContentBorder" Path="ActualWidth" />
<Binding ElementName="ContentItemsControl" Path="ActualWidth" />
</MultiBinding.Bindings>
</MultiBinding>
</ScrollBar.Visibility>
<ScrollBar.Triggers>
<EventTrigger RoutedEvent="MouseEnter"
SourceName="HorizontalBar">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HorizontalBar"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave"
SourceName="HorizontalBar">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="HorizontalBar"
Storyboard.TargetProperty="Opacity"
To="0.3"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ScrollBar.Triggers>
</ScrollBar>
<!--主内容纵向滚动-->
<ScrollBar x:Name="VerticalBar" Grid.Row="1" Grid.Column="1"
Orientation="Vertical"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Opacity="0.5"
ViewportSize="{Binding ElementName=ContentBorder, Path=ActualHeight}"
Minimum="0.0"
Value="0"
Cursor="Arrow"
>
<ScrollBar.Maximum>
<MultiBinding Mode="OneWay" Converter="{StaticResource ScrollBarMaximumConverter}">
<MultiBinding.Bindings>
<Binding ElementName="ContentBorder" Path="ActualHeight" />
<Binding ElementName="ContentItemsControl" Path="ActualHeight" />
</MultiBinding.Bindings>
</MultiBinding>
</ScrollBar.Maximum>
<ScrollBar.Visibility>
<MultiBinding Mode="OneWay" Converter="{StaticResource ScrollBarVisibilityConverter}">
<MultiBinding.Bindings>
<Binding ElementName="ContentBorder" Path="ActualHeight" />
<Binding ElementName="ContentItemsControl" Path="ActualHeight" />
</MultiBinding.Bindings>
</MultiBinding>
</ScrollBar.Visibility>
</ScrollBar>
</Grid>
</Grid>
</Window>
完整代码:
完结 撒花~ 匆忙写好 希望大家轻喷