WPF Canvas show custom control with ellipse filled with image and text,peridoically update via System.Timers.Timer and toggle on pause resume via button
//custom control <UserControl x:Class="WpfApp389.ElpImageTbk" 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:WpfApp389" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <Ellipse Fill="{Binding UCFillImgBrush,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Text="{Binding UCElpStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" Foreground="Red"/> </Grid> </UserControl> //custom control.cs using System; using System.Collections.Generic; 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 WpfApp389 { /// <summary> /// Interaction logic for ElpImageTbk.xaml /// </summary> /// public partial class ElpImageTbk : UserControl { public ElpImageTbk() { InitializeComponent(); this.DataContext = this; } public ImageBrush UCFillImgBrush { get { return (ImageBrush)GetValue(UCFillImgBrushProperty); } set { SetValue(UCFillImgBrushProperty, value); } } // Using a DependencyProperty as the backing store for UCFillImgBrush. This enables animation, styling, binding, etc... public static readonly DependencyProperty UCFillImgBrushProperty = DependencyProperty.Register("UCFillImgBrush", typeof(ImageBrush), typeof(ElpImageTbk), new PropertyMetadata(null)); public string UCElpStr { get { return (string)GetValue(UCElpStrProperty); } set { SetValue(UCElpStrProperty, value); } } // Using a DependencyProperty as the backing store for UCElpStr. This enables animation, styling, binding, etc... public static readonly DependencyProperty UCElpStrProperty = DependencyProperty.Register("UCElpStr", typeof(string), typeof(ElpImageTbk), new PropertyMetadata("")); } } //xaml.cs using System; using System.Collections.Generic; 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; using System.IO; namespace WpfApp389 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private Grid gd { get; set; } private Button btn { get; set; } private Canvas cvs { get; set; } private Random rnd { get; set; } private int width { get; set; } private int height { get; set; } private System.Timers.Timer tmr { get; set; } private bool IsPaused = false; public MainWindow() { InitializeComponent(); this.WindowState = WindowState.Maximized; gd = new Grid(); btn = new Button(); Grid.SetRow(btn, 0); Grid.SetColumn(btn, 0); btn.Width = 200; btn.Height = 50; btn.FontSize = 30; btn.Foreground = new SolidColorBrush(Colors.Red); btn.Content = "Pause"; btn.Click += Btn_Click; btn.TabIndex = 2; btn.HorizontalAlignment = HorizontalAlignment.Right; btn.VerticalAlignment = VerticalAlignment.Top; if (!gd.Children.Contains(btn)) { gd.Children.Add(btn); } cvs = new Canvas(); if (!gd.Children.Contains(cvs)) { gd.Children.Add((cvs)); } rnd = new Random(); this.Content = gd; this.Loaded += MainWindow_Loaded; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { width = (int)this.ActualWidth-100; height= (int)this.ActualHeight-100; RefreshData(); tmr = new System.Timers.Timer(); tmr.Elapsed += Tmr_Elapsed; tmr.Interval = 2000; tmr.Start(); } private void Tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if(IsPaused) { return; } Application.Current.Dispatcher.BeginInvoke(new Action(() => { RefreshData(); })); } private void Btn_Click(object sender, RoutedEventArgs e) { IsPaused = !IsPaused; if(IsPaused) { btn.Content = "Resume"; } else { btn.Content = "Pause"; } } private void RefreshData() { if (cvs != null) { cvs.Children.Clear(); var imgsList = Directory.GetFiles(@"../../Images"); if(imgsList!=null && imgsList.Any()) { int imgsCnt = imgsList.Count(); for(int i=0;i<50;i++) { ElpImageTbk elpImg = new ElpImageTbk(); elpImg.Width = 100; elpImg.Height = 50; BitmapImage bmp = new BitmapImage(); bmp.BeginInit(); bmp.UriSource=new Uri(imgsList[i%imgsCnt], UriKind.RelativeOrAbsolute); bmp.EndInit(); bmp.Freeze(); elpImg.UCFillImgBrush = new ImageBrush(bmp); elpImg.UCElpStr=(i+1).ToString(); Canvas.SetLeft(elpImg, rnd.Next(0, width)); Canvas.SetTop(elpImg, rnd.Next(0, height)); if(!cvs.Children.Contains(elpImg)) { cvs.Children.Add(elpImg); } } } } } } }