WPF implements a simple running horse lamp effect, while wpf implements a running horse Lamp
Recently, the project needs to use the running horse lamp. Unlike the online project, most of the online projects are continuous, and what we want is discontinuous.
That is, four items are displayed on the interface (the number of display items is variable). If seven items are to be displayed, the left hops are continuously made between the four spaces. Of course, the connection effect is not very good.
Then, you can click it to remove the content that is no longer displayed.
The effect is as follows:
The idea is roughly as follows:
1. A ViewBox is used in the outermost layer. In order to populate the place where the control is called, it is convenient to automatically stretch
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" layout = "Stretch" verticalAlignment = "Stretch" Stretch = "Fill"/>
2. Define three variables. One is the Count value to set the number of UserControl to be displayed. For example, the default value is 4. For example, if the value is set to 5, there are five items. 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 marquee.
3. Set a Canvas and place it in the Viewbox on the outermost layer for use when running a horse lamp (this is also a commonly used Canvas)
// Set some attributes for Canvas: canvas_board.verticalignment = verticalignment. stretch; canvas_board.HorizontalAlignment = HorizontalAlignment. stretch; canvas_board.Width = this. viewbox_main.ActualWidth; canvas_board.Height = this. viewbox_main.ActualHeight; canvas_board.ClipToBounds = true; // viewbox supports stretching this. viewbox_main.Child = canvas_board;
4. Place the Grid to be cyclic into the Canvas. The number of grids here is one greater than the number displayed, that is, Count + 1 value, because when scrolling, in fact, there is one on the outermost side, which ensures the cycle. As for the Margin between the two controls, this is to set the Grid. At that time, the control will be directly thrown into the Grid.
// Cyclically Add the Grid to the list to be displayed. for (int I = 0; I <Uc_Count + 1; I ++) {Grid 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, move the animation to the left.
For (int I = 0; I <UcListForShow. count; I ++) {// set the effect of DoubleAnimationUsingKeyFrames daukf_uc = new evaluate (); LinearDoubleKeyFrame kw.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 (kw.uc); daukf_uc.KeyFrames.Add (k2_uc); encrypt (daukf_uc); Storyboard. setTarget (daukf_uc, UcListForShow [I]); Storyboard. setTargetProperty (daukf_uc, new PropertyPath ("(Canvas. left )"));}
6. When scrolling, You need to calculate the Grid to which the UserControl is added, that is, which control is the first one.
We set an index value scroll_index. The default value is scroll_index = 0, which is the initial state. After rolling, scroll_index = scroll_index + 1-Uc_Count;
Then, judge whether the display list is at the end of the loop. If so, the control to be filled is scroll_index % UcListSum. count (rolling index, returns the remainder of the total number). If not, it is scroll_index ++ % UcListSum. count (rolling index ++, returns the remainder of the total number)
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 Usercontrol from the original one. Otherwise, an error will be thrown. Usercontrol already belongs to another control} UcListForShow [I]. children. clear (); UcListForShow [I]. children. add (uc); // Add the hidden Button to the Grid. Button btn = new Button (); btn. style = (dictionary ["hidenStyle"] as Style); // read the Style btn of the Button from the Style file. tag = UcListForShow [I]. children; // assign a value to the Tag to facilitate searching for btn. click + = Btn_Click; // register the hidden event UcListForShow [I]. children. add (btn );}
In the code, note that (uc. parent as Grid ). children. clear (). If it is not removed, the system will prompt that it already belongs to another one. Therefore, remove it from the parent.
7. Hidden events of the Button. After the Button is clicked, it is hidden. In fact, the total number is removed from the hidden items.
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) // when the number of lists is the same as the number to be displayed, stop the animation. {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 code is 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 MarqueeUserCont Rol {// <summary> // MarqueeUC. interaction logic of xaml // </summary> public partial class MarqueeUC: UserControl {ResourceDictionary dictionary; public MarqueeUC () {InitializeComponent (); // read the Style File dictionary = new ResourceDictionary {Source = new Uri ("/MarqueeUserControl; component/MarqueeUserControlDictionary. xaml ", UriKind. relative) };}# region attribute private int _ uc_Count = 0; // <summary> // used to display a few // /</Summary> public int Uc_Count {get {return _ uc_Count;} set {_ uc_Count = value ;}} private List <Grid> _ ucListForShow = new List <Grid> (); /// <summary> /// control List to be displayed /// </summary> private List <Grid> UcListForShow {get {return _ ucListForShow ;} set {_ ucListForShow = value ;}} private List <UserControl> _ ucListSum = new List <UserControl> (); /// <summary> /// list of controls to be added /// </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; // scroll width void GridLayout () {if (Uc_Count = 0) // if this value is not assigned a value, by default, four {Uc_Count = 4;} // you can specify the canvas_board.verticalignment = verticalignment attribute for the Canvas. stretch; canvas_bo Ard. horizontalAlignment = HorizontalAlignment. stretch; canvas_board.Width = this. viewbox_main.ActualWidth; canvas_board.Height = this. viewbox_main.ActualHeight; canvas_board.ClipToBounds = true; // viewbox supports stretching this. viewbox_main.Child = canvas_board; // cyclically 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 of DoubleAnimationUsingKeyFrames daukf_uc = new DoubleAnimationUsingKeyFrames (); LinearDoubleKeyFrame Kmeanuc = 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 (kw.uc); daukf_uc.KeyFrames.Add (k2_uc); encrypt (daukf_uc); Storyboard. setTarget (daukf_uc, UcLis TForShow [I]); Storyboard. setTargetProperty (daukf_uc, new PropertyPath ("(Canvas. left) ");} storyboard_imgs.FillBehavior = FillBehavior. stop; success + = Storyboard_imgs_Completed; success ();} 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 Usercontrol from the original one. Otherwise, an error will be thrown. Usercontrol already belongs to another control} UcListForShow [I]. children. clear (); UcListForShow [I]. children. add (uc); // Add the hidden Button to the Grid. Button btn = new Button (); btn. style = (dictionary ["hidenStyle"] as Style); // read the Style btn of the Button from the Style file. tag = UcListForShow [I]. children; // assign a value to the Tag to facilitate searching for btn. click + = Btn_Click; // register the hidden event 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) // when the number of lists is the same as the number to be displayed, stop the animation. {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. coun T];} 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 status, it will be returned directly and will no longer take effect {return;} if (storyboard_imgs.GetIsPaused () = true) // if it is in the paused status, start {storyboard_imgs.Begin () ;}} private void grid_main_MouseMove (object sender, MouseEventArgs e) {if (else () = 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 = "verticalignment "Value =" Center "/> <Setter Property =" Width "Value =" 25 "/> <Setter Property =" Height "Value =" 25 "/> <Setter Property = "BorderBrush" Value = "Transparent"/> <Setter Prop Erty = "BorderThickness" Value = "0"/> <Setter Property = "Template"> <! -- Put the Image in the Template for Content display. If you set an Image for Content separately, only one button will display the Image, and others will not be shown --> <Setter. value> <ControlTemplate TargetType = "{x: Type Button}"> <Border> <Image Source = "hiden.png"/> </Border> </ControlTemplate> </Setter. value> </Setter> </Style> </ResourceDictionary>
Unsolved Problems
When you want to add a mouse hover to the Button, it is displayed and hidden when it is removed, but it is difficult to hide it because when MouseOver is enabled, although the Visibility value has changed, however, the value of the Button is attached only at the next time. At this time, the value of the Button has been MouseLeave. Which of the following experts can guide you to see how to display and hide the Button.
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.