C# 在scrollviewer画布上确定用户单击的集合
我在开发基于MVVM的WPF应用程序时遇到了一个小障碍 我的愿望是能够告诉用户希望查看什么“bin”,因为通常情况下,事件多于视图中显示的事件。这基本上是一个小的stackpanel,它是在代码后面开发的,显示在用户选择的箱子上方。详情如下 基本背景是:C# 在scrollviewer画布上确定用户单击的集合,c#,wpf,xaml,scrollviewer,C#,Wpf,Xaml,Scrollviewer,我在开发基于MVVM的WPF应用程序时遇到了一个小障碍 我的愿望是能够告诉用户希望查看什么“bin”,因为通常情况下,事件多于视图中显示的事件。这基本上是一个小的stackpanel,它是在代码后面开发的,显示在用户选择的箱子上方。详情如下 基本背景是: 我正在记录ViewModel中发生的事件,我将它们称为事件 我在时间线上的视图中将它们显示为50x50画布(每个事件一个)。这里的细微差别是,我的空间非常有限,因此我将实际显示的事件数量限制为3个堆栈,每个时间段的事件数量略有偏移(只需想象卡
- 我正在记录ViewModel中发生的事件,我将它们称为事件
- 我在时间线上的视图中将它们显示为50x50画布(每个事件一个)。这里的细微差别是,我的空间非常有限,因此我将实际显示的事件数量限制为3个堆栈,每个时间段的事件数量略有偏移(只需想象卡片堆叠在后面,下面的卡片顶部和右侧被显示)
- 在每一个时间点(每30秒),画布向左滚动75个像素,当然,所有绘制的元素也随之移动。这也为活动设置了“箱子”。基本上,0到29.9秒之间的所有时间都在0仓,30到59.9秒是1仓,以此类推
- 我正在使用一个PreviewMouseLeftButtonDown事件,该事件链接到负责显示绑定事件的ItemsControl
- 向canvas元素添加一个标记,其中包含关于它所属的容器的信息。这不起作用,因为我获取的代码中的ItemsSource包含所有事件,而不仅仅是单击的事件。这是我访问ItemsSource的方式
private void ItemsControl_PreviewMouseLeftButtonDown( object sender, MouseButtonEventArds e) { var control = (ItemsControl)sender; var isource = control.ItemsSource; Debug.Assert(isource != null); }
- 在将其放入itemscontrol之前,我尝试将其嵌套在stackpanel中。当我有一个嵌套的列表时,它就起作用了,但当我不再拥有列表列表时,它就崩溃了。我也不确定这是否是一个可行的选择
<UserControl
x:Class="Removed.Views.TransitionTimeline"
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="ISTCanvasStyle" TargetType="Canvas">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style x:Key="ISTBorderStyle" TargetType="Border">
<Setter Property="BorderThickness" Value="3" />
<Setter Property="BorderBrush" Value="{Binding ColorBrush}" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="#FF555555" />
<Setter Property="Height" Value="50" />
<Setter Property="Width" Value="50" />
</Style>
<Style x:Key="ISTTextBlockStyle" TargetType="TextBlock">
<Setter Property="Text" Value="{Binding ShortName}" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="40" />
<Setter Property="Foreground" Value="White" />
<Setter Property="TextAlignment" Value="Center" />
</Style>
<Style x:Key="EventCountTextStyle" TargetType="TextBlock">
<Setter Property="Text" Value="{Binding ExtraEvents}" />
<Setter Property="Canvas.Top" Value="-15" />
<Setter Property="Canvas.Left" Value="-25" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="{Binding EventTextColorBrush}" />
<Setter Property="TextAlignment" Value="Center" />
</Style>
<DataTemplate x:Key="IndividualStateTransitions">
<Canvas Margin="{Binding Margin}" Style="{ StaticResource ISTCanvasStyle}" >
<Border Canvas.Left="-12.5" Style="{ StaticResource ISTBorderStyle}" >
<TextBlock Style="{StaticResource ISTTextBlockStyle}" />
</Border>
<TextBlock Style="{StaticResource EventCountTextStyle}" />
</Canvas>
</DataTemplate>
<DataTemplate x:Key="IST">
<ItemsControl
ItemsSource="{Binding}"
ItemTemplate="{StaticResource IndividualStateTransitions}"
PreviewMouseLeftButtonDown="ItemsControl_PreviewMouseLeftButtonDown"
Width="75">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</DataTemplate>
<DataTemplate x:Key="BottomTimeBar">
<Canvas>
<Line X1="{Binding DashX}" X2="{Binding DashX}" Y1="100" Y2="0" Stroke="#FF646464" StrokeThickness="1" StrokeDashArray="5" StrokeDashCap="Round" />
<TextBlock Canvas.ZIndex="-999" Width="50" TextAlignment="Center" Text="{Binding TimerText}" Canvas.Left="{Binding BlockLeft}"
Canvas.Top="85" Foreground="White" Background="#FF444444" FontSize="13" />
</Canvas>
</DataTemplate>
</UserControl.Resources>
<Grid Name="TimelineGrid" Height="192">
<Grid.RowDefinitions>
<RowDefinition Height="92" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Canvas Grid.Row="0" Width="1920" Height="100">
<ScrollViewer
Width="1920"
Height="100"
Name="_timelineScrollViewer2"
CanContentScroll="True"
Background="Transparent"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden">
<Canvas Width="9999" Name="_timelineCanvas2">
</Canvas>
</ScrollViewer>
</Canvas>
<Canvas Grid.Row="1" Name="MainCanvas" Width="1920" Height="100" >
<Line X1="0" X2="1920" Y1="0" Y2="0" Stroke="#FFD0D0D0" StrokeThickness="3">
<Line.Effect>
<DropShadowEffect BlurRadius="3" ShadowDepth="3" />
</Line.Effect>
</Line>
<Line X1="0" X2="1920" Y1="55" Y2="55" Stroke="#FFD0D0D0" StrokeThickness="3">
<Line.Effect>
<DropShadowEffect BlurRadius="3" ShadowDepth="3" />
</Line.Effect>
</Line>
<ScrollViewer
Width="1920"
Height="100"
Name="_timelineScrollViewer"
CanContentScroll="True"
Background="Transparent"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
PreviewMouseLeftButtonDown="TimelineScrollViewerLeftMouseDown"
PreviewMouseLeftButtonUp="LeftMouseUp"
PreviewMouseMove="TimelineScrollViewerMouseMove"
PreviewMouseWheel="TimelineScrollViewerPreviewMouseWheel"
ScrollChanged="OnTimelineScrollChanged" ClipToBounds="False">
<Canvas Width="9999" Name="_timelineCanvas">
<Line Canvas.ZIndex="-1000" Name="CurrentTimeLine" X1="1280" X2="1280" Y1="0" Y2="100" Stroke="#FFD0D0D0" StrokeThickness="3">
<Line.Effect>
<DropShadowEffect BlurRadius="3" ShadowDepth="3" />
</Line.Effect>
</Line>
<ItemsControl ItemsSource="{Binding BottomTimeBarData}" ItemTemplate="{StaticResource BottomTimeBar}" Canvas.Left="{Binding LeftScroll}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl ItemsSource="{Binding BottomTimeBarDataPast}" ItemTemplate="{StaticResource BottomTimeBar}" Canvas.Left="{Binding LeftScroll}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl ItemsSource="{Binding DisplayObject}" ItemTemplate="{StaticResource IndividualStateTransitions}" Canvas.Left="{Binding LeftScroll}" Canvas.Top="15" Margin="0.0, 25.5"
PreviewMouseLeftButtonDown="ItemsControl_PreviewMouseLeftButtonDown" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Canvas>
</ScrollViewer>
</Canvas>
</Grid>
</UserControl>
我订阅了一个事件聚合器,以便在发送事件时捕获它们。这将触发我的oneventereceived
方法。关于这个方法,您需要知道的是,它从它接收的事件中获取信息,并根据事件发生的时间确定它应该落入哪个容器中。这会触发对myDrawObject
方法的调用
如果您希望尝试并模拟这一点,您可以用一些硬编码的东西来代替stvm的使用。我无法提供这方面的实际数据。颜色只是一种表示事件类型的颜色。stvm.ShortName只是一个字母_bin只是一个列表
,用于跟踪各个bin中发生的事件总数<代码>位置只是它所属箱子中的数字事件。因此,如果这是第一个事件,将是1。如果这是第十个项目,那将是10个
此处的FindLastVisualChild
方法仅用于返回给定bin的第三个DisplayObject的位置索引。这允许我更新标记,该标记表示堆栈中存在“+X more.”事件
private void DrawObject( EventViewModel stvm, int position, int bin )
{
var margin = "";
var zindex = 0;
var left = bin * 75.0;
var textColor = Colors.Transparent;
var extraEvents = "+ ";
switch ( position )
{
case 1:
left += 12.5;
margin = left + ", -5";
zindex = 3;
DisplayObject.Add( new DisplayObjects
{
Color = stvm.Color,
ShortName = stvm.ShortName,
Margin = margin,
ZIndex = zindex,
EventTextColor = textColor,
ExtraEvents = extraEvents,
ElementBin = bin
} );
break;
case 2:
left += 22.5;
margin = left + ", -15";
zindex = 2;
DisplayObject.Add( new DisplayObjects
{
Color = stvm.Color,
ShortName = stvm.ShortName,
Margin = margin,
ZIndex = zindex,
EventTextColor = textColor,
ExtraEvents = extraEvents,
ElementBin = bin
} );
break;
case 3:
left += 32.5;
margin = left + ", -25";
zindex = 1;
DisplayObject.Add( new DisplayObjects
{
Color = stvm.Color,
ShortName = stvm.ShortName,
Margin = margin,
ZIndex = zindex,
EventTextColor = textColor,
ExtraEvents = extraEvents,
ElementBin = bin
} );
break;
default:
//left += 32.5;
//margin = left + ", -25";
//DisplayObject.Add( new DisplayObjects { Color = stvm.Color, ShortName = stvm.ShortName, Margin = margin, ZIndex = zindex, EventTextColor = textColor, ExtraEvents = extraEvents } );
extraEvents += ( _bins[bin] - 3 ) + " more.";
var test = FindLastVisualChild( bin );
DisplayObject[test].EventTextColor = Colors.White;
DisplayObject[FindLastVisualChild( bin )].ExtraEvents = extraEvents;
break;
}
}
private int FindLastVisualChild( int bin )
{
var sum = 0;
for ( var idx = 0; idx <= bin; idx++ )
if ( _bins[idx] <= 3 )
sum += _bins[idx];
else
sum += 3;
return ( sum - 1 );
}
private void DrawObject(EventViewModel stvm、int-position、int-bin)
{
var保证金=”;
var-zindex=0;
左变分=bin*75.0;
var textColor=颜色。透明;
var extraEvents=“+”;
开关(位置)
{
案例1:
左+=12.5;
边距=左+“,-5”;
zindex=3;
添加(新的显示对象)
{
Color=stvm.Color,
ShortName=stvm.ShortName,
保证金=保证金,
ZIndex=ZIndex,
EventTextColor=textColor,
外部事件=外部事件,
ElementBin=bin
} );
打破
案例2:
左+=22.5;
边距=左+“,-15”;
zindex=2;
添加(新的显示对象)
{
Color=stvm.Color,
ShortName=stvm.ShortName,
保证金=保证金,
ZIndex=ZIndex,
EventTextColor=textColor,
外部事件=外部事件,
ElementBin=bin
} );
打破
案例3:
左+=32.5;
边距=左+“,-25”;
zindex=1;
添加(新的显示对象)
{
Color=stvm.Color,
ShortName=stvm.ShortName,
保证金=保证金,
ZIndex=ZIndex,
EventTextColor=textColor,
外部事件=外部事件,
ElementBin=bin
} );
打破
违约:
//左+=32.5;
//边距=左+“,-25”;
//添加(新的显示对象{Color=stvm.Color,ShortName=stvm.ShortName,Margin=Margin,ZIndex=ZIndex,EventTextColor=textColor,ExtraEvents=ExtraEvents});
外部事件+=(\u bin[bin]-3)+“更多。”;
var测试=FindLastVisualChild(bin);
显示
private void DrawObject( EventViewModel stvm, int position, int bin )
{
var margin = "";
var zindex = 0;
var left = bin * 75.0;
var textColor = Colors.Transparent;
var extraEvents = "+ ";
switch ( position )
{
case 1:
left += 12.5;
margin = left + ", -5";
zindex = 3;
DisplayObject.Add( new DisplayObjects
{
Color = stvm.Color,
ShortName = stvm.ShortName,
Margin = margin,
ZIndex = zindex,
EventTextColor = textColor,
ExtraEvents = extraEvents,
ElementBin = bin
} );
break;
case 2:
left += 22.5;
margin = left + ", -15";
zindex = 2;
DisplayObject.Add( new DisplayObjects
{
Color = stvm.Color,
ShortName = stvm.ShortName,
Margin = margin,
ZIndex = zindex,
EventTextColor = textColor,
ExtraEvents = extraEvents,
ElementBin = bin
} );
break;
case 3:
left += 32.5;
margin = left + ", -25";
zindex = 1;
DisplayObject.Add( new DisplayObjects
{
Color = stvm.Color,
ShortName = stvm.ShortName,
Margin = margin,
ZIndex = zindex,
EventTextColor = textColor,
ExtraEvents = extraEvents,
ElementBin = bin
} );
break;
default:
//left += 32.5;
//margin = left + ", -25";
//DisplayObject.Add( new DisplayObjects { Color = stvm.Color, ShortName = stvm.ShortName, Margin = margin, ZIndex = zindex, EventTextColor = textColor, ExtraEvents = extraEvents } );
extraEvents += ( _bins[bin] - 3 ) + " more.";
var test = FindLastVisualChild( bin );
DisplayObject[test].EventTextColor = Colors.White;
DisplayObject[FindLastVisualChild( bin )].ExtraEvents = extraEvents;
break;
}
}
private int FindLastVisualChild( int bin )
{
var sum = 0;
for ( var idx = 0; idx <= bin; idx++ )
if ( _bins[idx] <= 3 )
sum += _bins[idx];
else
sum += 3;
return ( sum - 1 );
}
var canvas = e.OriginalSource as Canvas
var item = canvas.DataContext as MyItemViewModel;
var control = (Canvas)sender;
var item = control.DataContext as DisplayObjects;
var itembin = item.ElementBin;