前端页面:
<UserControl x:Class="QuJiao.BannerViewer"
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:QuJiao"
xmlns:quJiao="clr-namespace:QuJiao;assembly=QuJiaoManager"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<!-- board样式 -->
<Style x:Key="boardStyle" TargetType="Canvas">
<Setter Property="Width" Value="{Binding Path=ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"/>
<Setter Property="Height" Value="{Binding Path=ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"/>
<Setter Property="ClipToBounds" Value="True"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
</Style>
<!-- banner图片 -->
<Style x:Key="bannerImgStyle" TargetType="Image">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Width" Value="{Binding Path=ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"/>
<Setter Property="Height" Value="{Binding Path=ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"/>
<Setter Property="Stretch" Value="Fill"/>
</Style>
<!-- banner列表 -->
<Style x:Key="bannerImgListStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="BorderThickness" Value="0"/>
<!-- 可以隐藏不可禁用,否则不能滚动了 -->
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<ScrollViewer x:Name="imgScroll"
Tag="imgScroll"
Style="{StaticResource ScrollViewerThin}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<!-- 点击广告 -->
<Grid Tag="{Binding redirect_url}" MouseUp="ItemImg_OnMouseUp">
<Image x:Name="itemImg" Style="{StaticResource bannerImgStyle}" Source="{Binding image_url,Converter={StaticResource ConvertNameToBitmapImage}}"/>
</Grid>
<DataTemplate.Triggers>
<!-- 有链接时鼠标变为手型 -->
<DataTrigger Binding="{Binding redirect_url,Converter={StaticResource BoolConvertStringIfNullOrEmpty}}" Value="False">
<Setter Property="Cursor" Value="Hand"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 导航圆点 -->
<Style x:Key="dot" TargetType="Ellipse">
<Setter Property="Width" Value="8"/>
<Setter Property="Height" Value="8"/>
<Setter Property="Fill" Value="White"/>
</Style>
<!-- 导航列表 -->
<Style x:Key="dotListStyle" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Grid>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="Margin" Value="10,0,0,0"/>
<Setter Property="Opacity" Value="0.5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="1"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Opacity" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Ellipse Style="{StaticResource dot}" Width="9" Height="9"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 导航按钮 -->
<Style x:Key="naviBtn" TargetType="quJiao:ButtonWithIcon">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Width" Value="38"/>
<Setter Property="Height" Value="38"/>
<Setter Property="IconWidth" Value="38"/>
<Setter Property="IconHeight" Value="38"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="quJiao:ButtonWithIcon">
<Image x:Name="img" Source="{TemplateBinding IconPath}" Width="{TemplateBinding IconWidth}" Height="{TemplateBinding IconHeight}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" TargetName="img" Value="{Binding Path=SecondIconPath,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=quJiao:ButtonWithIcon}}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Source" TargetName="img" Value="{Binding Path=SecondIconPath,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=quJiao:ButtonWithIcon}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="grid"
MouseEnter="OnMouseEnter"
MouseLeave="OnMouseLeave"
Width="{Binding Path=ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"
Height="{Binding Path=ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- banner图片 -->
<Canvas x:Name="canvas"
Grid.Column="0" Grid.ColumnSpan="3"
Style="{StaticResource boardStyle}">
<Image Name="image1" Style="{StaticResource bannerImgStyle}" MouseUp="ItemImg_OnMouseUp" Source="{Binding Path=ImageUrl1,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer},Converter={StaticResource ConvertNameToBitmapImage}}"/>
<Image Name="image2" Style="{StaticResource bannerImgStyle}" MouseUp="ItemImg_OnMouseUp" Source="{Binding Path=ImageUrl2,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer},Converter={StaticResource ConvertNameToBitmapImage}}"/>
</Canvas>
<!-- 向左翻页(默认隐藏,移入显示) -->
<quJiao:ButtonWithIcon Grid.Column="0" Margin="10,0,0,0"
Visibility="Collapsed"
Style="{StaticResource naviBtn}"
Name="btnLeft"
IconPath="/QuJiaoResource;component/Resource/Image/Home/QualityCourseware/CourseDetail/LeftPage.png"
SecondIconPath="/QuJiaoResource;component/Resource/Image/Home/QualityCourseware/CourseDetail/LeftPageClick.png"
Click="BtnLeft_Click"/>
<!-- 向右翻页(默认隐藏,移入显示) -->
<quJiao:ButtonWithIcon Grid.Column="2" Margin="0,0,10,0"
Visibility="Collapsed"
Style="{StaticResource naviBtn}"
Name="btnRight"
IconPath="/QuJiaoResource;component/Resource/Image/Home/QualityCourseware/CourseDetail/RightPage.png"
SecondIconPath="/QuJiaoResource;component/Resource/Image/Home/QualityCourseware/CourseDetail/RightPageClick.png"
Click="BtnRight_Click"/>
<!-- 导航圆点 -->
<ListBox x:Name="dotList"
Grid.Column="0" Grid.ColumnSpan="3"
Style="{StaticResource dotListStyle}"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,24,15"
SelectedIndex="{Binding Path=SelectedIndex,Mode=TwoWay,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"
ItemsSource="{Binding Path=BannerList,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:BannerViewer}}"/>
</Grid>
</UserControl>
后端页面:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
// ReSharper disable MemberCanBeMadeStatic.Local
namespace QuJiao
{
public class BannerModel
{
public string image_url { get; set; }
public string redirect_url { get; set; }
}
/// <summary>
/// QujiaoBanner.xaml 的交互逻辑
/// </summary>
public partial class BannerViewer : UserControl, INotifyPropertyChanged
{
readonly TimeSpan interval = new TimeSpan(0, 0, 0, 0, 300);
readonly Timer timer = new Timer();
bool isPlayingAnim = false;
/// <summary>
/// 滚动宽度
/// </summary>
double RollWidth => canvas.ActualWidth;
public BannerViewer()
{
InitializeComponent();
// 设置计时器
timer.Interval = 5000;// 默认5秒轮播
timer.Elapsed += (sender, e) => Application.Current.Dispatcher?.BeginInvoke(new Action(Next));
}
#region 绑定属性
#region BannerList
public static readonly DependencyProperty BannerListProperty = DependencyProperty.Register(
"BannerList", typeof(IList<BannerModel>),
typeof(BannerViewer),
new PropertyMetadata(null, (d, e) =>
{
var uc = (BannerViewer)d;
var list = (IList<BannerModel>)e.NewValue;
if (list != null && list.Count > 1)
{
uc.SelectedIndex = 0;
uc.timer.Start();
}
else
{
uc.timer.Stop();
}
}));
public IList<BannerModel> BannerList
{
get => (IList<BannerModel>)GetValue(BannerListProperty);
set => SetValue(BannerListProperty, value);
}
#endregion
#region SwitchInterval
public static readonly DependencyProperty SwitchIntervalProperty = DependencyProperty.Register(
"SwitchInterval", typeof(double),
typeof(BannerViewer),
new PropertyMetadata(5000d, null, (d, baseValue) =>
{
var uc = (BannerViewer)d;
var res = (double)baseValue;
if (res > 0)
{
uc.timer.Interval = res;
}
return res;
}));
public double SwitchInterval
{
get => (double)GetValue(SwitchIntervalProperty);
set => SetValue(SwitchIntervalProperty, value);
}
#endregion
#endregion
#region 界面属性
#region RaisePropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public virtual void RaisePropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected void Set<T>(ref T field, T newValue, string propertyName)
{
field = newValue;
RaisePropertyChanged(propertyName);
}
#endregion
int selectedIndex = 0;
/// <summary>
/// 当前选中
/// </summary>
public int SelectedIndex
{
get => selectedIndex;
set
{
Set(ref selectedIndex, value, "SelectedIndex");
SelectedIndexChange(value);
}
}
string imageUrl1 = null;
/// <summary>
/// 图片1
/// </summary>
public string ImageUrl1
{
get => imageUrl1;
set => Set(ref imageUrl1, value, "ImageUrl1");
}
string imageUrl2 = null;
/// <summary>
/// 图片2
/// </summary>
public string ImageUrl2
{
get => imageUrl2;
set => Set(ref imageUrl2, value, "ImageUrl2");
}
#endregion
#region 属性变更事件
void SelectedIndexChange(int value)
{
if (rollAnim != null)
{
rollAnim.Stop(image1);
rollAnim.Stop(image2);
}
if (BannerList != null && 0 <= value && value < BannerList.Count)
{
var model = BannerList[selectedIndex];
ImageUrl(model.image_url, model.image_url);
}
}
#endregion
#region 动画事件
/// <summary>
/// 滚动动画
/// </summary>
Storyboard rollAnim { get; set; }
/// <summary>
/// 设置图片路径
/// </summary>
void ImageUrl(string url1, string url2)
{
if (BannerList.Count <= 0 || string.IsNullOrEmpty(url1) || string.IsNullOrEmpty(url2))
{
ImageUrl1 = null;
ImageUrl2 = null;
}
else
{
ImageUrl1 = url1;
ImageUrl2 = url2;
}
}
/// <summary>
/// 播放完成位置
/// </summary>
void Position(double pos1, double pos2)
{
image1.SetValue(Canvas.LeftProperty, pos1);
image2.SetValue(Canvas.LeftProperty, pos2);
}
/// <summary>
/// 获得轮播动画
/// </summary>
void BeginAnim(double fpos1, double tpos1, double fpos2, double tpos2)
{
var keyTime1 = KeyTime.FromTimeSpan(TimeSpan.Zero);
var keyTime2 = KeyTime.FromTimeSpan(interval);
isPlayingAnim = true;
// 设置动画
if (rollAnim != null)
{
rollAnim.Children.Clear();
}
else
{
rollAnim = new Storyboard();
}
#region 图片1动画
var keyFrames1 = new DoubleAnimationUsingKeyFrames();
keyFrames1.KeyFrames.Add(new LinearDoubleKeyFrame(fpos1, keyTime1));
keyFrames1.KeyFrames.Add(new LinearDoubleKeyFrame(tpos1, keyTime2));
Storyboard.SetTarget(keyFrames1, image1);
Storyboard.SetTargetProperty(keyFrames1, new PropertyPath("(Canvas.Left)"));
#endregion
#region 图片2动画
var keyFrames2 = new DoubleAnimationUsingKeyFrames();
keyFrames2.KeyFrames.Add(new LinearDoubleKeyFrame(fpos2, keyTime1));
keyFrames2.KeyFrames.Add(new LinearDoubleKeyFrame(tpos2, keyTime2));
Storyboard.SetTarget(keyFrames2, image2);
Storyboard.SetTargetProperty(keyFrames2, new PropertyPath("(Canvas.Left)"));
#endregion
rollAnim.Children.Add(keyFrames1);
rollAnim.Children.Add(keyFrames2);
rollAnim.FillBehavior = FillBehavior.Stop;
rollAnim.Begin();
TimerHelper.Deley(interval.Milliseconds / 10, delegate
{
isPlayingAnim = false;
});
}
#endregion
#region 切换图片
void Prev()
{
if (isPlayingAnim) return;
var max = BannerList.Count - 1;
var prevIndex = SelectedIndex;
int thisIndex;
// 切换位置
if (SelectedIndex > 0)
{
SelectedIndex--;
}
else
{
SelectedIndex = max;
}
if (SelectedIndex == max)
{
prevIndex = 0;
thisIndex = max;
}
else if (SelectedIndex == 0)
{
prevIndex = 1;
thisIndex = 0;
}
else
{
thisIndex = SelectedIndex;
}
var url1 = BannerList[prevIndex].image_url;
var url2 = BannerList[thisIndex].image_url;
ImageUrl(url1, url2);
Position(-RollWidth, 0);
BeginAnim(0, RollWidth, -RollWidth, 0);
}
void Next()
{
if (isPlayingAnim) return;
var max = BannerList.Count - 1;
var prevIndex = SelectedIndex;
// 切换位置
if (SelectedIndex < max)
{
SelectedIndex++;
}
else
{
SelectedIndex = 0;
}
var thisIndex = SelectedIndex;
var url1 = BannerList[prevIndex].image_url;
var url2 = BannerList[thisIndex].image_url;
ImageUrl(url1, url2);
Position(-RollWidth, 0);
BeginAnim(0, -RollWidth, RollWidth, 0);
}
#endregion
/// <summary>
/// 向左翻页
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void BtnLeft_Click(object sender, RoutedEventArgs e)
{
Prev();
}
/// <summary>
/// 向右翻页
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void BtnRight_Click(object sender, RoutedEventArgs e)
{
Next();
}
/// <summary>
/// 点击课件详情
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ItemImg_OnMouseUp(object sender, MouseButtonEventArgs e)
{
try
{
var model = BannerList[selectedIndex];
var url = model.redirect_url;
MessengerHelper.Send((ushort)QualityCoursewareEvents.NavigateToBannerDetail, url);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 鼠标移入
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnMouseEnter(object sender, MouseEventArgs e)
{
btnLeft.Visibility = Visibility.Visible;
btnRight.Visibility = Visibility.Visible;
}
/// <summary>
/// 鼠标移出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnMouseLeave(object sender, MouseEventArgs e)
{
btnLeft.Visibility = Visibility.Hidden;
btnRight.Visibility = Visibility.Hidden;
}
}
}