How to get the time elapsed from storyboard ? The time elapsed needs to display according to the rectangle fill.
MainWindow.xaml
<Window
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:wpf_ItemsControl_Wrapped"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="wpf_ItemsControl_Wrapped.MainWindow"
mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"><Window.Resources><local:BorderClipConverter x:Key="BClipConverter"/></Window.Resources><Grid><Grid.Resources><Style TargetType="{x:Type Button}"><Setter Property="Margin" Value="4"/></Style></Grid.Resources><Grid.RowDefinitions><RowDefinition Height="Auto" /><RowDefinition Height="Auto" /><RowDefinition Height="Auto" /><RowDefinition Height="*"/></Grid.RowDefinitions><StackPanel Orientation="Horizontal" Grid.Row="1" Margin="4, 8, 4, 8"><TextBlock Text="Current Value:" VerticalAlignment="Center" /><TextBlock Text="{Binding CurrentValue}" Margin="15, 0, 0, 0" VerticalAlignment="Center" /></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="2" Margin="4, 8, 4, 8"><TextBlock Text="Time Elapsed: " VerticalAlignment="Center" /><!--TBC--><!--<TextBlock Text="x" VerticalAlignment="Center" />--></StackPanel><ListBox x:Name="lb"
Grid.Row="3" Grid.IsSharedSizeScope="True" AlternationCount="10000" ItemsSource="{Binding Models}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"><ListBox.ItemContainerStyle><Style TargetType="{x:Type ListBoxItem}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBoxItem}"><ContentPresenter/></ControlTemplate></Setter.Value></Setter></Style></ListBox.ItemContainerStyle><ListBox.ItemsPanel><ItemsPanelTemplate><WrapPanel Orientation="Horizontal" Margin="15, 0, 15, 0" /></ItemsPanelTemplate></ListBox.ItemsPanel><ListBox.ItemTemplate><DataTemplate><Grid><Grid.RowDefinitions><RowDefinition Height="Auto" /><RowDefinition Height="50" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition MinWidth="150" SharedSizeGroup="AllSameWidth" /></Grid.ColumnDefinitions><Grid><Border
BorderThickness="1" BorderBrush="Gray" Height="50"><Border.Clip><MultiBinding Converter="{StaticResource BClipConverter}"><Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/><Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/><Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}"/></MultiBinding></Border.Clip><!--<Border.Effect><DropShadowEffect /></Border.Effect>--><Border.Style><Style TargetType="{x:Type Border}"><Style.Triggers><DataTrigger Binding="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="0"><Setter Property="CornerRadius" Value="10, 0, 0, 10" /></DataTrigger><DataTrigger Binding="{Binding IsLastItem, ElementName=lastInLine}"
Value="true" ><Setter Property="CornerRadius" Value="0, 10, 10, 0" /></DataTrigger><DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" Value="1"><Setter Property="CornerRadius" Value="10, 10, 10, 10" /></DataTrigger></Style.Triggers></Style></Border.Style><local:ItemTracer Width="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Container="{Binding ., RelativeSource={RelativeSource AncestorType={x:Type WrapPanel}}}"
ContainerWidth="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type WrapPanel}}}"
ItemIndex="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"
ItemsCount="{Binding Items.Count, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
x:Name="lastInLine" /></Border><Border
Name="TopBorder"
BorderThickness="1" BorderBrush="Gray" Height="50"><Border.Style><Style TargetType="{x:Type Border}"><Style.Triggers><DataTrigger Binding="{Binding (ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="0"><Setter Property="CornerRadius" Value="10, 0, 0, 10" /></DataTrigger><DataTrigger Binding="{Binding IsLastItem, ElementName=lastInLine}"
Value="true" ><Setter Property="CornerRadius" Value="0, 10, 10, 0" /></DataTrigger><DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" Value="1"><Setter Property="CornerRadius" Value="10, 10, 10, 10" /></DataTrigger></Style.Triggers></Style></Border.Style></Border><TextBlock Text="{Binding CurrentValue}" VerticalAlignment="Center" HorizontalAlignment="Center" /></Grid><TextBlock Text="{Binding StartTime, StringFormat=\{0:mm\\:ss\}}" Grid.Row="1" Margin="-14, 0, 0, 0" /><TextBlock Text="{Binding EndTime, StringFormat=\{0:mm\\:ss\}}" Grid.Row="1" HorizontalAlignment="Right"><TextBlock.RenderTransform><TranslateTransform X="14" Y="0" /></TextBlock.RenderTransform><TextBlock.Style><Style TargetType="{x:Type TextBlock}"><Setter Property="Visibility" Value="Visible"/><Style.Triggers><MultiDataTrigger><MultiDataTrigger.Conditions><Condition Binding="{Binding IsLastInLine, ElementName=lastInLine}" Value="False" /><Condition Binding="{Binding IsLastItem, ElementName=lastInLine}" Value="False" /></MultiDataTrigger.Conditions><Setter Property="Visibility" Value="Collapsed" /></MultiDataTrigger></Style.Triggers></Style></TextBlock.Style></TextBlock></Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid></Window>MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace wpf_ItemsControl_Wrapped
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MainWindowViewModel mainWindowViewModel;
public MainWindow()
{
InitializeComponent();
mainWindowViewModel = new MainWindowViewModel();
DataContext = mainWindowViewModel;
ContentRendered += MainWindow_ContentRendered;
}
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
IList<ItemTracer> itemTracers = new List<ItemTracer>();
foreach (Model model in lb.Items)
{
ListBoxItem lbi = lb.ItemContainerGenerator.ContainerFromItem(model) as ListBoxItem;
ItemTracer tracer = FindVisualChild<ItemTracer>(lbi);
itemTracers.Add(tracer);
}
mainWindowViewModel.ItemTracers = new ReadOnlyCollection<ItemTracer>(itemTracers);
mainWindowViewModel.Start();
}
private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child is childItem)
{
return (childItem)child;
}
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
}
}
MainWindowViewModel.cs
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Media.Animation;
namespace wpf_ItemsControl_Wrapped
{
public class MainWindowViewModel : ViewModelBase
{
private ObservableCollection<Model> models;
public ObservableCollection<Model> Models
{
get
{
if (models == null)
{
models = new ObservableCollection<Model>();
}
return models;
}
}
private TimeSpan stepTime = TimeSpan.FromSeconds(15);
public TimeSpan StepTime
{
get { return stepTime; }
set
{
stepTime = value;
}
}
private ReadOnlyCollection<ItemTracer> itemTracers;
public ReadOnlyCollection<ItemTracer> ItemTracers
{
get { return itemTracers; }
set
{
itemTracers = value;
}
}
private string currentValue;
public string CurrentValue
{
get { return currentValue; }
set
{
currentValue = value;
OnPropertyChanged("CurrentValue");
}
}
private int currentValueCount = 0;
public MainWindowViewModel()
{
Random rand = new Random();
Models.Add(new Model { StartTime = LastEnd(), Duration = TimeSpan.FromSeconds(10), CurrentValue = rand.Next() });
Models.Add(new Model { StartTime = LastEnd(), Duration = TimeSpan.FromSeconds(20), CurrentValue = rand.Next() });
Models.Add(new Model { StartTime = LastEnd(), Duration = TimeSpan.FromSeconds(30), CurrentValue = rand.Next() });
Models.Add(new Model { StartTime = LastEnd(), Duration = TimeSpan.FromSeconds(40), CurrentValue = rand.Next() });
Models.Add(new Model { StartTime = LastEnd(), Duration = TimeSpan.FromSeconds(50), CurrentValue = rand.Next() });
Models.Add(new Model { StartTime = LastEnd(), Duration = TimeSpan.FromSeconds(60), CurrentValue = rand.Next() });
}
public void Start()
{
for (int i = 0; i < itemTracers.Count(); i++)
{
Storyboard itemTracerStoryboard = itemTracers[i].progressRectangle.Resources["sb"] as Storyboard;
itemTracerStoryboard.Completed += ItemTracerStoryboard_Completed;
itemTracerStoryboard.Begin();
}
UpdateCurrentValue();
}
private void ItemTracerStoryboard_Completed(object sender, EventArgs e)
{
UpdateCurrentValue();
}
public TimeSpan LastEnd()
{
return (Models.Count == 0) ? TimeSpan.FromSeconds(0) : Models.Last<Model>().EndTime;
}
private void UpdateCurrentValue()
{
CurrentValue = Models[currentValueCount].CurrentValue.ToString();
if (currentValueCount != Models.Count() - 1)
{
currentValueCount++;
}
}
}
}ItemTracer.xaml
<UserControl x:Class="wpf_ItemsControl_Wrapped.ItemTracer"
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"
xmlns:local="clr-namespace:wpf_ItemsControl_Wrapped"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"><Grid><Border
Name="progressRectangle"
Height="10" Background="SkyBlue" VerticalAlignment="Bottom"><Border.RenderTransform><ScaleTransform ScaleX="0" ScaleY="1"/></Border.RenderTransform><Border.Resources><Storyboard x:Key="sb"><DoubleAnimation
Storyboard.TargetName="progressRectangle"
Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleX)"
From="0"
To="1"
AutoReverse="False"
FillBehavior="HoldEnd"
BeginTime="{Binding StartTime}"
Duration="{Binding DurationStoryboard}"
/></Storyboard></Border.Resources></Border></Grid></UserControl>ItemTracer.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace wpf_ItemsControl_Wrapped
{
public partial class ItemTracer : UserControl
{
public ItemTracer()
{
InitializeComponent();
EvaluateIsLastInLine(this);
EvaluateIsLastItem(this);
}
public bool IsLastInLine
{
get { return (bool)GetValue(IsLastInLineProperty); }
set { SetValue(IsLastInLineProperty, value); }
}
public static readonly DependencyProperty IsLastInLineProperty = DependencyProperty.Register("IsLastInLine", typeof(bool), typeof(ItemTracer), new PropertyMetadata(false));
public double ContainerWidth
{
get { return (double)GetValue(ContainerWidthProperty); }
set { SetValue(ContainerWidthProperty, value); }
}
public static readonly DependencyProperty ContainerWidthProperty = DependencyProperty.Register("ContainerWidth", typeof(double), typeof(ItemTracer), new PropertyMetadata(0.0, new PropertyChangedCallback(OnContainerWidthChanged)));
public UIElement Container
{
get { return (UIElement)GetValue(ContainerProperty); }
set { SetValue(ContainerProperty, value); }
}
public static readonly DependencyProperty ContainerProperty = DependencyProperty.Register("Container", typeof(UIElement), typeof(ItemTracer));
public int ItemsCount
{
get { return (int)GetValue(ItemsCountProperty); }
set { SetValue(ItemsCountProperty, value); }
}
public static readonly DependencyProperty ItemsCountProperty = DependencyProperty.Register("ItemsCount", typeof(int), typeof(ItemTracer), new PropertyMetadata(0, new PropertyChangedCallback(OnItemsCountChanged)));
public int ItemIndex
{
get { return (int)GetValue(ItemIndexProperty); }
set { SetValue(ItemIndexProperty, value); }
}
public static readonly DependencyProperty ItemIndexProperty = DependencyProperty.Register("ItemIndex", typeof(int), typeof(ItemTracer), new PropertyMetadata(0, new PropertyChangedCallback(OnItemIndexChanged)));
public bool IsLastItem
{
get { return (bool)GetValue(IsLastItemProperty); }
set { SetValue(IsLastItemProperty, value); }
}
public static readonly DependencyProperty IsLastItemProperty = DependencyProperty.Register("IsLastItem", typeof(bool), typeof(ItemTracer), new PropertyMetadata(false));
private static void OnContainerWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EvaluateIsLastInLine(d);
}
private static void EvaluateIsLastInLine(DependencyObject d)
{
bool _isLastInLine = false;
ItemTracer _this = (ItemTracer)d;
Point relativeLocation = _this.TranslatePoint(new Point(0, 0), (UIElement)_this.GetValue(ContainerProperty));
double leftInRow = (double)_this.GetValue(ContainerWidthProperty) - relativeLocation.X;
if (leftInRow < ((double)_this.GetValue(ActualWidthProperty) * 2))
{
_isLastInLine = true;
}
_this.SetCurrentValue(IsLastInLineProperty, _isLastInLine);
}
private static void OnItemsCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EvaluateIsLastItem(d);
}
private static void OnItemIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EvaluateIsLastItem(d);
}
private static void EvaluateIsLastItem(DependencyObject d)
{
ItemTracer _this = (ItemTracer)d;
bool _isLastItem = false;
//Debug.WriteLine(_this.GetValue(ItemIndexProperty).ToString() + " of " + _this.GetValue(ItemsCountProperty).ToString());
if ((int)_this.GetValue(ItemsCountProperty) - (int)_this.GetValue(ItemIndexProperty) == 1)
{
_isLastItem = true;
}
_this.SetCurrentValue(IsLastItemProperty, _isLastItem);
}
}
}