타임 라인으로 약간의로드 블록을 쳤습니다. MVVM 기반 WPF 응용 프로그램에서 개발 중입니다.scrollviewer 캔버스에서 사용자가 클릭 한 컬렉션 결정
내 욕망은 일반적으로보기에 표시되는 것보다 많은 이벤트가 있기 때문에 사용자가보고 싶은 "빈"을 말할 수 있어야합니다. 이것은 근본적으로 코드 숨김으로 개발되어 사용자가 선택한 빈 위에 표시되는 작은 작은 스택 패널 일 것입니다. 자세한 내용은 아래를 참조하십시오. 그들은 뷰 모델에서 발생하는 I 이벤트를 기록하고
, 내가 이벤트로 참조합니다 :
기본 배경이있다.
시간 표시 막대에서보기에 50x50 캔버스 (이벤트 당 하나씩)로 표시 중입니다. 여기서 뉘앙스는 공간의 양이 매우 제한되어 있기 때문에 표시되는 실제 이벤트 수를 약간 오프셋 된 3 개의 스택으로 제한합니다 (표시된 카드 아래에있는 카드의 위쪽과 오른쪽에 서로 쌓인 카드를 상상해보십시오).)를 각각의 타임 블록에 대해 할당한다.
각 시간마다 (30 초마다) 캔버스가 왼쪽으로 75 픽셀 스크롤되고 모든 그려진 요소가 물론 함께 움직입니다. 또한 이벤트에 대한 "휴지통"을 설정합니다. 본질적으로 0과 29.9 초 사이의 모든 것은 bin 0에 있고, 30 - 59.9는 bin 1입니다.
바운드 이벤트를 표시하는 ItemsControl에 연결된 PreviewMouseLeftButtonDown 이벤트를 사용하고 있습니다.
현재 모든 기능이 작동합니다. 마우스 클릭을 수집 할 수 있으며 클릭 한 이벤트 그룹을 결정하기 위해 몇 가지 기본 수학을 사용하려고했습니다. 이것은 클릭 할 때 마우스의 X 위치를 기반으로하고 ScrollViewer 창의 모든 스크롤을 고려한 것입니다. 불행히도 나는 정확한 "bin"을 얻지 못했습니다. 내가 시도
다른 것들 :
이가 소속 된 빈에 대한 정보를 포함하는 캔버스 요소에 태그에 추가합니다. 내가 얻은 코드의 ItemsSource에는 클릭 한 이벤트뿐만 아니라 모든 이벤트가 포함되어 있기 때문에 이는 작동하지 않습니다. 이것이 ItemsSource에 액세스하는 방법입니다.
private void ItemsControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArds e) { var control = (ItemsControl)sender; var isource = control.ItemsSource; Debug.Assert(isource != null); }
나는 ItemsControl에로 퍼팅하기 전에 StackPanel에의 내부를 둥지를 시도했습니다. 이것은 중첩 목록이있을 때 효과적 이었지만 목록 목록을 얻지 못하면 무너졌습니다. 이 시점에서 실행 가능한 옵션이 될지 확실하지 않습니다.
나는 (그것을 참조 할 수 있습니다 사람들을 위해) 이것을 가지고 XAML은 다음과 같습니다 :이 그리는 데 사용되는 DataTemplate을 주택으로 관심의
주요 ItemsControl에 마지막 하나입니다 ScrollViewer에서 캔버스의 이벤트. 나머지 두 개는 타임 라인의 맨 아래에있는 타임 스탬프 용입니다.
<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>
질문 사항이 있으면 알려주십시오. 무슨 일이 일어나는지 분명히 밝히는 것이 행복 할 것 같습니다.궁극적으로 내가 찾고있는 것은 사용자가보고 싶은 "bin"을 결정하는 방법입니다.
업데이트 1 : 그려진 개체에 대한 추가 정보.
내 자신의 내부 클래스를 정의 했으므로 ObservableCollection의 데이터 유형으로 사용할 수 있습니다.이 데이터는이 경우에 바인딩됩니다.
internal class DisplayObjects : INotifyPropertyChanged
{
private int _elementbin;
public int ElementBin
{
get { return _elementbin; }
set
{
_elementbin = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ElementBin"));
}
}
private string _shortName;
public string ShortName
{
get { return _shortName; }
set
{
_shortName = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ShortName"));
}
}
private string _margin;
public string Margin
{
get { return _margin; }
set
{
_margin = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Margin"));
}
}
private string _extraevents;
public string ExtraEvents
{
get { return _extraevents; }
set
{
_extraevents = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ExtraEvents"));
}
}
public Color EventTextColor { get; set; }
public SolidColorBrush EventTextColorBrush
{
get
{
return new SolidColorBrush(EventTextColor);
}
}
private int _zindex;
public int ZIndex
{
get { return _zindex; }
set
{
_zindex = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ZIndex"));
}
}
public Color Color { get; set; }
public SolidColorBrush ColorBrush
{
get { return new SolidColorBrush(Color); }
}
public event PropertyChangedEventHandler PropertyChanged;
}
이벤트 수집기에 가입되어 이벤트를 전송할 때이를 잡을 수 있습니다. 내 OnEventReceived
메서드가 트리거됩니다. 이 방법에 대해 알아야 할 것은 이벤트가 수신 한 이벤트에서 정보를 가져 와서 이벤트가 발생한 시간을 기준으로 어떤 bin으로 분류해야하는지 결정하는 것입니다. 이 내 DrawObject
메서드에 대한 호출을 트리거합니다.
이것을 시도하고 싶다면 stvm을 하드 코딩 된 것으로 바꿀 수 있습니다. 내가 실제 데이터를 제공 할 수는 없습니다. stvm.Color는 이벤트 유형을 나타내는 색상입니다. stvm.ShortName은 하나의 문자입니다. _bin은 각 bin에서 발생한 총 이벤트 수를 추적하는 List<Int>
입니다. position
은 속한 빈의 숫자 이벤트입니다. 첫 번째 이벤트가 1 일 경우 첫 번째 이벤트입니다. 10 번째 이벤트이면 10이됩니다.
FindLastVisualChild
메서드는 주어진 DisplayObject에 대한 세 번째 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);
}
왜 'ItemsControl' 대신'ItemsControl'의 개별 항목에 클릭 이벤트를 추가하지 않으시겠습니까? – Rachel
나는 그것을 지금 시도했다. 실제로 사용자가 클릭 한 캔버스를 가져 와서 해당 캔버스의 하위 항목에 액세스 할 수 있습니다. 그러나 내가 실제로 캔버스에 배치 한 태그를 실제로 얻을 수 있는지는 확실하지 않습니다. 이것은 실제로 내가 속한 bin을 식별 할 수있는 지점까지 나를 데려다주지는 않습니다. –