WPF realizes simple running lamp effect

Time:2021-9-9

In recent projects, the effect of the running lantern will be used. What is different from the Internet is that most of the Internet are continuous, while what we require is discontinuous.

In other words, four items are displayed on the interface (the number of items displayed is variable). If there are seven items to be displayed, they will constantly jump left in the four spaces. Of course, the connection effect is not very good.

Then, click to remove the content that is no longer displayed.

The effects are as follows:

The idea is as follows:

1. The outermost layer uses a viewbox to fill the place where this control is called, which can facilitate automatic stretching

Copy codeThe code is as follows:
<Viewbox x:Name=”viewbox_main” Height=”{Binding Path=ActualHeight}” Width=”{Binding Path=ActualWidth}” MouseLeave=”grid_main_MouseLeave” MouseMove=”grid_main_MouseMove”  HorizontalAlignment=”Stretch” VerticalAlignment=”Stretch” Stretch=”Fill”/>

2. Three variables are defined. One is the count value to set the number of UserControls to be displayed. For example, the default is 4, as shown in the effect drawing. Of course, if it is set to 5, it is 5; A list < grid > is used to put the list of display controls, and a list < UserControl > is used to put all the controls to be used in the running lantern.

3. Set a canvas and put it into the viewbox on the outermost layer, which is used for the running lantern (this is also the commonly used running lantern control canvas)

//Set some properties for canvas
 canvas_board.VerticalAlignment = VerticalAlignment.Stretch;
 canvas_board.HorizontalAlignment = HorizontalAlignment.Stretch;
canvas_board.Width = this.viewbox_main.ActualWidth;
canvas_board.Height = this.viewbox_main.ActualHeight;
canvas_board.ClipToBounds = true;
//Stretching can be supported with viewbox
this.viewbox_main.Child = canvas_board;

4. Put the grid to be cycled into the canvas. The number of grids here is one larger than the number displayed, that is, count + 1 value, because there is actually one on the outermost side when scrolling, so as to ensure the circulation. As for the margin between the two controls, this is to set the grid. At that time, the controls will be directly thrown into the grid

//Loop to add the grid to the list to be displayed
for (int i = 0; i < Uc_Count + 1; i++)
{
 Grid grid = new Grid();
 grid.Width = canvas_board.Width / Uc_Count - 10;
 grid.Height = canvas_board.Height - 10;
 grid.Margin = new Thickness(5);
 this.canvas_board.Children.Add(grid);
 grid.SetValue(Canvas.TopProperty, 0.0);
 grid.SetValue(Canvas.LeftProperty, i * (grid.Width + 10));

 UcListForShow.Add(grid);
}

5. Add an animation effect to each grid, that is, the effect of moving to the left

for (int i = 0; i < UcListForShow.Count; i++)
{
 //Set the effect when scrolling
 DoubleAnimationUsingKeyFrames daukf_uc = new DoubleAnimationUsingKeyFrames();
 LinearDoubleKeyFrame k1_uc = new LinearDoubleKeyFrame(i * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2)));
 LinearDoubleKeyFrame k2_uc = new LinearDoubleKeyFrame((i - 1) * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5)));
 daukf_uc.KeyFrames.Add(k1_uc);
 daukf_uc.KeyFrames.Add(k2_uc);
 storyboard_imgs.Children.Add(daukf_uc);
 Storyboard.SetTarget(daukf_uc, UcListForShow[i]);
 Storyboard.SetTargetProperty(daukf_uc, new PropertyPath("(Canvas.Left)"));
}

6. When scrolling, it is necessary to calculate which grid the UserControl is added to, that is, which control is the first.

We set an index value scroll_ Index. By default, scroll_ Index = 0, which is the initial state. When scrolling, scroll_ index = scroll_ index + 1 – Uc_ Count;

Then, judge whether the end of the display list is displayed during the loop. If so, the control to be filled is scroll_ Index% uclistsum.count (scroll the index and directly take the remainder of the total). If not, it is scroll_ Index + +% uclistsum. Count (scroll index + +, and directly take the remainder of the total)

scroll_index = scroll_index + 1 - Uc_Count;

for (int i = 0; i < UcListForShow.Count; i++)
{
 UcListForShow[i].SetValue(Canvas.LeftProperty, i * (UcListForShow[i].Width + 10));
 UserControl uc;
 if (i == UcListForShow.Count - 1)
 {
  uc = UcListSum[scroll_index % UcListSum.Count];
 }
 else
 {
  uc = UcListSum[scroll_index++ % UcListSum.Count];
 }
 if (uc.Parent != null)
 {
  (uc.Parent as Grid).Children.Clear();// Remove the UserControl from the original inside, otherwise it will throw an error. The UserControl already belongs to another control
 }
 UcListForShow[i].Children.Clear();
 UcListForShow[i].Children.Add(uc);
 //Add hidden button to grid
 Button btn = new Button();
 btn.Style = (dictionary["hidenStyle"] as Style);// Read the button style from the style file
 btn.Tag = UcListForShow[i].Children;// Assign a value to tag so that it is easy to find
 btn.Click += Btn_ Click;// Register hidden events
 UcListForShow[i].Children.Add(btn);
}

In the code, it should be noted that (UC. Parent as grid). Children. Clear(). If it is not removed, it will prompt that it already belongs to another one, so it should be removed from the parent.

7. The hidden event of a button is hidden when the button is clicked. In fact, the item that is no longer displayed is subtracted from the total number

private void Btn_Click(object sender, RoutedEventArgs e)
{
 if ((sender as Button).Tag != null)
 {
  UcListSum.Remove((((sender as Button).Tag as UIElementCollection)[0] as UserControl));
 }
 If (uclistsum. Count = = uc_count) // stop the animation effect when the number of lists is the same as the number to be displayed
 {
  storyboard_imgs.Completed -= Storyboard_imgs_Completed;
  storyboard_imgs.Stop();
  for (int i = 0; i < Uc_Count; i++)
  {
   UcListForShow[i].Children.Clear();
   if (UcListSum[i].Parent != null)
   {
    (UcListSum[i].Parent as Grid).Children.Clear();
   }
   UcListForShow[i].Children.Add(UcListSum[i]);
  }
  return;
 }
}

All codes are as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MarqueeUserControl
{
 /// <summary>
 ///Interactive logic of marqueeuc.xaml
 /// </summary>
 public partial class MarqueeUC : UserControl
 {
  ResourceDictionary dictionary;
  public MarqueeUC()
  {
   InitializeComponent();
   //Read style file
   dictionary = new ResourceDictionary { Source = new Uri("/MarqueeUserControl;component/MarqueeUserControlDictionary.xaml", UriKind.Relative) };
  }
  #Region attribute
  private int _uc_Count = 0;
  /// <summary>
  ///Used to show several
  /// </summary>
  public int Uc_Count
  {
   get
   {
    return _uc_Count;
   }

   set
   {
    _uc_Count = value;
   }
  }

  private List<Grid> _ucListForShow = new List<Grid>();
  /// <summary>
  ///List of controls to display
  /// </summary>
  private List<Grid> UcListForShow
  {
   get
   {
    return _ucListForShow;
   }

   set
   {
    _ucListForShow = value;
   }
  }

  private List<UserControl> _ucListSum = new List<UserControl>();
  /// <summary>
  ///List of controls to add
  /// </summary>
  public List<UserControl> UcListSum
  {
   get
   {
    return _ucListSum;
   }

   set
   {
    _ucListSum = value;
   }
  }

  #endregion
  Canvas canvas_board = new Canvas();
  Storyboard storyboard_imgs = new Storyboard();
  int scroll_ index = 0;// Scroll index
  double scroll_ width;// Rolling width

  void GridLayout()
  {
   If (uc_count = = 0) // if this value is not assigned, four are displayed by default
   {
    Uc_Count = 4;
   }
   //Set some properties for canvas
   canvas_board.VerticalAlignment = VerticalAlignment.Stretch;
   canvas_board.HorizontalAlignment = HorizontalAlignment.Stretch;
   canvas_board.Width = this.viewbox_main.ActualWidth;
   canvas_board.Height = this.viewbox_main.ActualHeight;
   canvas_board.ClipToBounds = true;
   //Stretching can be supported with viewbox
   this.viewbox_main.Child = canvas_board;
   //Loop to add the grid to the list to be displayed
   for (int i = 0; i < Uc_Count + 1; i++)
   {
    Grid grid = new Grid();
    grid.Width = canvas_board.Width / Uc_Count - 10;
    grid.Height = canvas_board.Height - 10;
    grid.Margin = new Thickness(5);
    this.canvas_board.Children.Add(grid);
    grid.SetValue(Canvas.TopProperty, 0.0);
    grid.SetValue(Canvas.LeftProperty, i * (grid.Width + 10));

    UcListForShow.Add(grid);
   }
  }

  void StoryLoad()
  {
   for (int i = 0; i < UcListForShow.Count; i++)
   {// set the effect when scrolling
    DoubleAnimationUsingKeyFrames daukf_uc = new DoubleAnimationUsingKeyFrames();
    LinearDoubleKeyFrame k1_uc = new LinearDoubleKeyFrame(i * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2)));
    LinearDoubleKeyFrame k2_uc = new LinearDoubleKeyFrame((i - 1) * (UcListForShow[i].Width + 10), KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2.5)));
    daukf_uc.KeyFrames.Add(k1_uc);
    daukf_uc.KeyFrames.Add(k2_uc);
    storyboard_imgs.Children.Add(daukf_uc);
    Storyboard.SetTarget(daukf_uc, UcListForShow[i]);
    Storyboard.SetTargetProperty(daukf_uc, new PropertyPath("(Canvas.Left)"));
   }

   storyboard_imgs.FillBehavior = FillBehavior.Stop;
   storyboard_imgs.Completed += Storyboard_imgs_Completed;
   storyboard_imgs.Begin();
  }

  private void Storyboard_imgs_Completed(object sender, EventArgs e)
  {

   scroll_index = scroll_index + 1 - Uc_Count;

   for (int i = 0; i < UcListForShow.Count; i++)
   {
    UcListForShow[i].SetValue(Canvas.LeftProperty, i * (UcListForShow[i].Width + 10));
    UserControl uc;
    if (i == UcListForShow.Count - 1)
    {
     uc = UcListSum[scroll_index % UcListSum.Count];
    }
    else
    {
     uc = UcListSum[scroll_index++ % UcListSum.Count];
    }
    if (uc.Parent != null)
    {
     (uc.Parent as Grid).Children.Clear();// Remove the UserControl from the original inside, otherwise it will throw an error. The UserControl already belongs to another control
    }
    UcListForShow[i].Children.Clear();
    UcListForShow[i].Children.Add(uc);
    //Add hidden button to grid
    Button btn = new Button();
    btn.Style = (dictionary["hidenStyle"] as Style);// Read the button style from the style file
    btn.Tag = UcListForShow[i].Children;// Assign a value to tag so that it is easy to find
    btn.Click += Btn_ Click;// Register hidden events
    UcListForShow[i].Children.Add(btn);
   }

   storyboard_imgs.Begin();
  }

  private void Btn_Click(object sender, RoutedEventArgs e)
  {
   if ((sender as Button).Tag != null)
   {
    UcListSum.Remove((((sender as Button).Tag as UIElementCollection)[0] as UserControl));
   }
   If (uclistsum. Count = = uc_count) // stop the animation effect when the number of lists is the same as the number to be displayed
   {
    storyboard_imgs.Completed -= Storyboard_imgs_Completed;
    storyboard_imgs.Stop();
    for (int i = 0; i < Uc_Count; i++)
    {
     UcListForShow[i].Children.Clear();
     if (UcListSum[i].Parent != null)
     {
      (UcListSum[i].Parent as Grid).Children.Clear();
     }
     UcListForShow[i].Children.Add(UcListSum[i]);
    }
    return;
   }
  }

  public void StartMar()
  {
   GridLayout();

   scroll_width = this.canvas_board.Width;

   for (int i = 0; i < UcListForShow.Count; i++)
   {
    UserControl uc;
    if (i == UcListForShow.Count - 1)
    {
     uc = UcListSum[scroll_index % UcListSum.Count];
    }
    else
    {
     uc = UcListSum[scroll_index++ % UcListSum.Count];
    }
    if (uc.Parent != null)
    {
     (uc.Parent as Grid).Children.Clear();
    }
    UcListForShow[i].Children.Clear();
    UcListForShow[i].Children.Add(uc);
   }
   StoryLoad();
  }

  private void grid_main_MouseLeave(object sender, MouseEventArgs e)
  {
   If (storyboard_imgs. Getcurrentstate() = = clockstate. Stopped) // if it is in the stopped state, it will be returned directly and will no longer work
   {
    return;
   }
   If (storyboard_imgs. Getispaused() = = true) // if it is suspended, start
   {
    storyboard_imgs.Begin();
   }
  }

  private void grid_main_MouseMove(object sender, MouseEventArgs e)
  {
   if (storyboard_imgs.GetIsPaused() == false)
   {
    storyboard_imgs.Pause();
   }
  }
 }
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="clr-namespace:MarqueeUserControl">
 <Style TargetType="Button" x:Key="hidenStyle">
  <Setter Property="Background" Value="Transparent"/>
  <Setter Property="HorizontalAlignment" Value="Center"/>
  <Setter Property="VerticalAlignment" Value="Center"/>
  <Setter Property="Width" Value="25"/>
  <Setter Property="Height" Value="25"/>
  <Setter Property="BorderBrush" Value="Transparent"/>
  <Setter Property="BorderThickness" Value="0"/>
  <Setter Property="Template"><!-- Put the image into the template to display as content. If the image is set separately for content, there is only one button to display the image, and the others are not displayed -- >
   <Setter.Value>
    <ControlTemplate TargetType="{x:Type Button}">
     <Border>
      <Image Source="hiden.png"/>
     </Border>
    </ControlTemplate>
   </Setter.Value>
  </Setter>
 </Style>
</ResourceDictionary>

Unsolved problems

I want to add the button to display when hovering and hide when removing, but I find it difficult to use. The reason is that when mouseover goes up, although the visibility value changes, the button value will not be attached until the next time. At this time, it has been mouseleave. Please ask which God to guide and see how to do this display and hiding.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.

Recommended Today

Beautify your code VB (VBS) code formatting implementation code

However, vb.net does have many new functions that VB6 does not have. The automatic typesetting of code is one, which is the function we want to realize today – VB code formatting.Let’s look at the effect: Before formatting: Copy codeThe code is as follows: For i = 0 To WebBrowser1.Document.All.length – 1 If WebBrowser1.Document.All(i).tagName = […]