当前位置: 首页 > news >正文

商城网站建设模板下载长春seo网站排名

商城网站建设模板下载,长春seo网站排名,邢台专业网站建设公司,公司经营范围网站开发及运营想做一个下图所示的Slider,以冒泡的方式显示其Value值,该怎么做呢? 功能要求,当鼠标放在滑块上的时候,冒“泡”显示值;当滑块移动的时候,“泡”跟随移动。 看似简单的功能,但要完美…

想做一个下图所示的Slider,以冒泡的方式显示其Value值,该怎么做呢?

在这里插入图片描述

功能要求,当鼠标放在滑块上的时候,冒“泡”显示值;当滑块移动的时候,“泡”跟随移动。

看似简单的功能,但要完美实现,确实要花费不少心思的。

方法一:使用Canvas面板。

  1. 改造Slider
    Slider的样式改造,比较简单,重写其模板即可。
  <Slider.Template><ControlTemplate TargetType="Slider"><Border Name="border" SnapsToDevicePixels="True"Background="{TemplateBinding Panel.Background}" BorderBrush="{TemplateBinding Border.BorderBrush}" BorderThickness="{TemplateBinding Border.BorderThickness}" ><Grid><Border Background="Gray" Height="4" CornerRadius="2"/><Track Name="PART_Track" Grid.Row="1"><Track.DecreaseRepeatButton><RepeatButton><RepeatButton.Template><ControlTemplate TargetType="RepeatButton"><Border Height="4" CornerRadius="2" Background="#FF006CBE"/></ControlTemplate></RepeatButton.Template></RepeatButton></Track.DecreaseRepeatButton><Track.Thumb><Thumb Name="thumb" VerticalAlignment="Center" Focusable="False"><Thumb.Template><ControlTemplate TargetType="Thumb"><Grid><Ellipse Name="thumbEllipse" Width="10" Height="10" Fill="White" StrokeThickness="1" Stroke="#FF006CBE" /></Grid></ControlTemplate></Thumb.Template></Thumb></Track.Thumb></Track></Grid></Border></ControlTemplate></Slider.Template></Slider>
  1. 添加“泡”
    很明显,这个“泡”的形状、文字都是一个元素,因此需要使用面板来将两个元素组合起来。这里最好使用Canvas,因为它的子元素是绝对定位的,可以通过Canvas.Left、Canvas.Top等属性安排子元素的位置,且Canvas也不会影响父元素的布局。因此将Slider的模板继续改造一下,如下所示:
 <Slider Name="slider" Width="255"><Slider.Template><ControlTemplate TargetType="Slider"><Border Name="border" SnapsToDevicePixels="True"Background="{TemplateBinding Panel.Background}" BorderBrush="{TemplateBinding Border.BorderBrush}" BorderThickness="{TemplateBinding Border.BorderThickness}" ><Grid><Border Background="Gray" Height="4" CornerRadius="2"/><Track Name="PART_Track" Grid.Row="1"><Track.DecreaseRepeatButton><RepeatButton><RepeatButton.Template><ControlTemplate TargetType="RepeatButton"><Border Height="4" CornerRadius="2" Background="#FF006CBE"/></ControlTemplate></RepeatButton.Template></RepeatButton></Track.DecreaseRepeatButton><Track.Thumb><Thumb Name="thumb" VerticalAlignment="Center" Focusable="False"><Thumb.Template><ControlTemplate TargetType="Thumb"><Grid><Ellipse Name="thumbEllipse" Width="10" Height="10" Fill="White" StrokeThickness="1" Stroke="#FF006CBE" /><Canvas Name="canvas" Opacity="0"><Grid Canvas.Bottom="10" Canvas.Left="-8"><Path Width="25" Stretch="Uniform" Fill="White" Stroke="#FF006CBE" StrokeThickness="1" Data="M172,633.14a339.4,339.4,0,0,1-169.9-294C2.13,151.76,154.2-.29,341.57-.29S681,151.76,681,339.11a339.38,339.38,0,0,1-169.9,294h0a183.88,183.88,0,0,0-84.27,106.38h0l-85.26,283.61L256.3,739.52A183.88,183.88,0,0,0,172,633.14Z"/><TextBlock HorizontalAlignment="Center" Margin="0,5,0,0" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Slider}, Path=Value, Converter={StaticResource double2Int}}"/></Grid></Canvas></Grid><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter TargetName="canvas" Property="Opacity" Value="1"/></Trigger><Trigger Property="IsDragging" Value="True"><Setter TargetName="canvas" Property="Opacity" Value="1"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Thumb.Template></Thumb></Track.Thumb></Track></Grid></Border></ControlTemplate></Slider.Template></Slider>

红色部分为添加的代码。有两点需要注意:

  1. TextBlock.Text属性的绑定,使用了RelativeSource模式。

  2. 记得要添加触发器(Trigger),使的Canvas能在指定的状态下显示出来。

以这种方式改的Slider控件,有一个问题:“泡”不能超出窗体显示。也就是说当滑块处于屏幕的边缘时,这个“泡”是显示不出来的。

方法二:使用Window
WPF框架中有Popup控件和Tooltip控件。通过微软的源代码可知,他们的实现都是使用Window控件。即在一定的条件下打开一个Windows,并显示内容,在另一个条件下,则关闭这个Window。

根据这个思路,就可以自定义一个控件,并实现更多的功能

  1. 自定义控件
    控件类:FellowPopup,其他的几个类为辅助类。
/// <summary>
/// 坐标系转换类
/// </summary>
public static class CoordinateHelper
{/// <summary>/// 将用户空间坐标系的点,转换为屏幕坐标系的点。/// 已考虑系统Dpi问题/// </summary>/// <param name="relativeTo">可视化对象。它的坐标系原点在左上角</param>/// <param name="point">在可视化对象坐标系中的点</param>/// <returns></returns>public static Point ClientToScreen(Visual relativeTo, Point point){if (relativeTo == null) return point;Point targetToScreen = relativeTo.PointToScreen(point);            // 将point的点转换为屏幕坐标系的点var source = PresentationSource.FromVisual(relativeTo);double dpiX = 96.0, dpiY = 96.0;if (source?.CompositionTarget != null){dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;}return new Point(targetToScreen.X * 96.0 / dpiX, targetToScreen.Y * 96 / dpiY);}
}public static class DependencyPropertyHelper
{/// <summary>/// 为依赖属性注册值发生改变时的回调方法/// </summary>/// <param name="Register">含有依赖属性的对象</param>/// <param name="dependencyProperty">依赖属性</param>/// <param name="action">要注册的值发生改变时的回调方法</param>/// <param name="runOnceImmediately">是否立即执行一次</param>public static void RegisterDependencyPropertyChanged(this DependencyObject Register, DependencyProperty dependencyProperty, EventHandler action, bool runOnceImmediately = false){DependencyPropertyDescriptor obj = DependencyPropertyDescriptor.FromProperty(dependencyProperty, Register.GetType());if(obj != null) obj.AddValueChanged(Register, action);if(runOnceImmediately) action?.Invoke(Register,new EventArgs());}
}/// <summary>
/// 放置模式
/// </summary>
public enum PlacementMode
{/// <summary>/// 顶部靠左/// </summary>TopLeft,/// <summary>/// 顶部居中/// </summary>TopMiddle,/// <summary>/// 顶部靠右/// </summary>TopRight,/// <summary>/// 左侧居中/// </summary>LeftMiddle,/// <summary>/// 右侧居中/// </summary>RightMiddle,/// <summary>/// 底部靠左/// </summary>BottomLeft,/// <summary>/// 底部居中/// </summary>BottomMiddle,/// <summary>/// 底部靠右/// </summary>BottomRight
}/// <summary>
/// 可跟随控件移动的弹出提示框。
/// </summary>
public class FellowPopup : ContentControl
{private Window _popupWnd;/// <summary>/// 水平位置偏移量/// </summary>public double HorizontalOffset{get => (double)GetValue(HorizontalOffsetProperty);set => SetValue(HorizontalOffsetProperty, value);}internal static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(FellowPopup), new PropertyMetadata(0.0d, OnValueChanged));/// <summary>/// 垂直偏移量/// </summary>public double VerticalOffset{get => (double)GetValue(VerticalOffsetProperty);set => SetValue(VerticalOffsetProperty, value);}internal static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset", typeof(double), typeof(FellowPopup), new PropertyMetadata(0.0d, OnValueChanged));/// <summary>/// 放置位置/// </summary>public PlacementMode Placement{get => (PlacementMode)GetValue(PlacementProperty);set => SetValue(PlacementProperty, value);}internal static readonly DependencyProperty PlacementProperty = DependencyProperty.Register("Placement", typeof(PlacementMode), typeof(FellowPopup), new PropertyMetadata(PlacementMode.BottomRight,OnValueChanged));/// <summary>/// 放置的目标元素/// </summary>public FrameworkElement PlacementTarget{get => (FrameworkElement)GetValue(PlacementTargetProperty);set => SetValue(PlacementTargetProperty, value);}internal static readonly DependencyProperty PlacementTargetProperty = DependencyProperty.Register("PlacementTarget", typeof(FrameworkElement), typeof(FellowPopup), new PropertyMetadata(null,OnValueChanged));private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){FellowPopup popup = (FellowPopup)d;popup.UpdateLocation();}/// <summary>/// 是否打开。当其为true时,则显示提示框,false则不显示提示框/// </summary>public bool IsOpen{get => (bool)GetValue(IsOpenProperty);set => SetValue(IsOpenProperty, value);}internal static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(FellowPopup), new PropertyMetadata(false,OnIsOpenChanged));private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){FellowPopup fp = d as FellowPopup;if((bool)e.NewValue ) fp.Open();else  fp.Close();}#region 触发位置更新/// <summary>/// 触发位置更新的控件/// </summary>public FrameworkElement TriggerElement{get => (FrameworkElement)GetValue(TriggerElementProperty);set => SetValue(TriggerElementProperty, value);}internal static readonly DependencyProperty TriggerElementProperty = DependencyProperty.Register("TriggerElement", typeof(UIElement), typeof(FellowPopup), new PropertyMetadata(null, OnTriggerChanged));/// <summary>/// 触发位置更新的控件的属性/// 此属性应该是TriggerElement的属性。/// 当此属性的值发生变化时,会触发FellowPopup的UpdateLocation方法。/// </summary>public DependencyProperty TriggerProperty{get => (DependencyProperty)GetValue(TriggerPropertyProperty);set => SetValue(TriggerPropertyProperty, value);}internal static readonly DependencyProperty TriggerPropertyProperty = DependencyProperty.Register("TriggerProperty", typeof(DependencyProperty), typeof(FellowPopup), new PropertyMetadata(null, OnTriggerChanged));private static void OnTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){FellowPopup fp = (FellowPopup)d;if (fp.TriggerElement == null || fp.TriggerProperty == null) return;// 如果定义属性的类,与TriggerElement类相同,或者TriggerElement类是它的子类Type propertyType = fp.TriggerProperty.OwnerType;Type elementType = fp.TriggerElement.GetType();if ((elementType != propertyType) && (!elementType.IsSubclassOf(propertyType))) throw new ArgumentException("TriggerElement不包含TriggerProperty属性");DependencyPropertyHelper.RegisterDependencyPropertyChanged(fp.TriggerElement, fp.TriggerProperty, delegate (object sender, EventArgs args){fp.UpdateLocation();}, false);}#endregionstatic FellowPopup(){DefaultStyleKeyProperty.OverrideMetadata(typeof(FellowPopup), new FrameworkPropertyMetadata(typeof(FellowPopup)));}/// <summary>/// 打开窗体/// </summary>private void Open(){_popupWnd = new Window(){Topmost = true,ShowActivated = false,AllowsTransparency = true,WindowStyle = WindowStyle.None,BorderThickness = new Thickness(0),SizeToContent = SizeToContent.WidthAndHeight,WindowStartupLocation = WindowStartupLocation.Manual,Background = this.Background,Content = this.Content,ContentStringFormat = this.ContentStringFormat,ContentTemplate = this.ContentTemplate,ContentTemplateSelector = this.ContentTemplateSelector,};UpdateLocation();_popupWnd.Show();}// 关闭_popup窗体,并回收private void Close(){if (_popupWnd != null){_popupWnd.Close();GC.SuppressFinalize(_popupWnd);}}/// <summary>/// 更新弹出窗体的位置。/// </summary>private void UpdateLocation(){if (_popupWnd == null) return;if(PlacementTarget == null){_popupWnd.Left = 0;_popupWnd.Top = 0;return;}double contentWidth = _popupWnd.Content == null ? 0 : ((FrameworkElement)_popupWnd.Content).ActualWidth;double contentHeght = _popupWnd.Content == null ? 0 : ((FrameworkElement)_popupWnd.Content).ActualHeight;Point targetToScreen;switch (Placement){case PlacementMode.TopLeft:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget,new Point(0, 0));_popupWnd.Left = targetToScreen.X - contentWidth - HorizontalOffset;_popupWnd.Top = targetToScreen.Y - contentHeght - VerticalOffset;break;case PlacementMode.TopMiddle:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(PlacementTarget.ActualWidth/2, 0));_popupWnd.Left = targetToScreen.X - contentWidth / 2 + HorizontalOffset;_popupWnd.Top = targetToScreen.Y - contentHeght - VerticalOffset;break;case PlacementMode.TopRight:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(PlacementTarget.ActualWidth, 0));_popupWnd.Left = targetToScreen.X + HorizontalOffset;_popupWnd.Top = targetToScreen.Y - contentHeght - VerticalOffset;break;case PlacementMode.LeftMiddle:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(0, PlacementTarget.ActualHeight / 2));_popupWnd.Left = targetToScreen.X - contentWidth - HorizontalOffset;_popupWnd.Top = targetToScreen.Y - contentHeght / 2;break;case PlacementMode.RightMiddle:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(PlacementTarget.ActualWidth, PlacementTarget.ActualHeight / 2));_popupWnd.Left = targetToScreen.X + HorizontalOffset;_popupWnd.Top = targetToScreen.Y - contentHeght / 2;break;case PlacementMode.BottomLeft:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(0, PlacementTarget.ActualHeight));_popupWnd.Left = targetToScreen.X - contentWidth - HorizontalOffset;_popupWnd.Top = targetToScreen.Y + VerticalOffset;break;case PlacementMode.BottomMiddle:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(PlacementTarget.ActualWidth / 2, PlacementTarget.ActualHeight));_popupWnd.Left = targetToScreen.X - contentWidth / 2 - HorizontalOffset;_popupWnd.Top = targetToScreen.Y + VerticalOffset;break;case PlacementMode.BottomRight:targetToScreen = CoordinateHelper.ClientToScreen(PlacementTarget, new Point(PlacementTarget.ActualWidth, PlacementTarget.ActualHeight));_popupWnd.Left = targetToScreen.X + HorizontalOffset;_popupWnd.Top = targetToScreen.Y + VerticalOffset;break;}}
}

(1)在FellowPopup类中,定义了一个Window类型的变量_popup,用于展示“泡”的内容。PlacementTarget、Placement、HorizontalOffset、VerticalOffset四个属性,用于设置_popup的Left和Top属性,以确定_popup在屏幕中的位置。

这里需要注意,Visual.PointToScreen()方法,参数point是在Visual坐标空间的点,其返回值为将这个点,转换为屏幕坐标系的点。但转换后的点,未考虑到系统DPI及屏幕缩放的情况。因此,需要将这个点再运算,使之成为当前屏幕DPI及缩放模式下的点坐标。

(2)TriggerElement、TriggerProperty属性,用于指示,当哪个元素的哪个属性值发生变化时,更新位置。

要想让一个窗体跟着控件移动,就必须告诉窗体,控件当前的位置在哪儿,然后去计算窗体应该在哪儿。而在WPF中,几乎没有控件会实时报告自己的位置。因此,必须找到元素的一个属性,当元素的“位置”发生改变的时候,这个属性值会发生变化。

除了找到这样的一个属性外,还需要注册一个属性值发生改变时的回调方法。在本例中,滑块在滑动的过程中,本身没有属性(公开的)值发生改变,但是Slider的Value属性会发生改变。因此可以选择它,来触发FellowPopup的位置改变。

由此可见,PlacementTarge系列与TriggerElement可以是不同的。一个用于“布置”窗体,一个用于“触发”窗体。

  1. 使用自定义控件
    定义好了控件后,就可以在Xaml中使用它了。继续改造Slider的模板:

     <!-- 别忘了转换器 --><local:Double2IntConverter  x:Key="double2Int" /> <Slider Name="slider" Width="255"><Slider.Template><ControlTemplate TargetType="Slider"><Border Name="border" SnapsToDevicePixels="True"Background="{TemplateBinding Panel.Background}" BorderBrush="{TemplateBinding Border.BorderBrush}" BorderThickness="{TemplateBinding Border.BorderThickness}" ><Grid><Border Background="Gray" Height="4" CornerRadius="2"/><Track Name="PART_Track" Grid.Row="1"><Track.DecreaseRepeatButton><RepeatButton><RepeatButton.Template><ControlTemplate TargetType="RepeatButton"><Border Height="4" CornerRadius="2" Background="#FF006CBE"/></ControlTemplate></RepeatButton.Template></RepeatButton></Track.DecreaseRepeatButton><Track.Thumb><Thumb Name="thumb" VerticalAlignment="Center" Focusable="False"><Thumb.Template><ControlTemplate TargetType="Thumb"><Grid><Ellipse Name="thumbEllipse" Width="10" Height="10" Fill="White" StrokeThickness="1" Stroke="#FF006CBE" /><local:FellowPopup x:Name="popup" Background="Transparent"Placement="TopMiddle" PlacementTarget="{Binding ElementName=thumbEllipse}"TriggerElement="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Slider}}"TriggerProperty="Slider.Value"><Grid HorizontalAlignment="Center" VerticalAlignment="Center"><Path Width="25" Stretch="Uniform" Fill="White" Stroke="#FF006CBE" StrokeThickness="1" Data="M172,633.14a339.4,339.4,0,0,1-169.9-294C2.13,151.76,154.2-.29,341.57-.29S681,151.76,681,339.11a339.38,339.38,0,0,1-169.9,294h0a183.88,183.88,0,0,0-84.27,106.38h0l-85.26,283.61L256.3,739.52A183.88,183.88,0,0,0,172,633.14Z"/><TextBlock HorizontalAlignment="Center" Margin="0,5,0,0" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Slider}, Path=Value, Converter={StaticResource double2Int}}"/></Grid></local:FellowPopup></Grid><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter TargetName="popup" Property="IsOpen" Value="True"/></Trigger><Trigger Property="IsDragging" Value="True"><Setter TargetName="popup" Property="IsOpen" Value="True"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Thumb.Template></Thumb></Track.Thumb></Track></Grid></Border></ControlTemplate></Slider.Template></Slider>
    

复制代码
注意Placement、TriggerElement、TriggerProperty、Text等属性的绑定方式。

至此,改造搞定。以第二种方式改造的Slider,“泡”可以显示在主窗体之上。没有任何东西会挡住他,以为它是TopMost的。另外也可以再添加自己的逻辑去设置“泡”的位置。

以上为自己学习总结,如有错误,请指正。

http://www.zhongyajixie.com/news/56831.html

相关文章:

  • 网站建设制作设计营销公司杭州站长工具浪潮
  • 哪个网站可以做创意短视频建个网站费用多少
  • 自己做网站别人怎么看见搜索关键词排名推广
  • 永年企业做网站推广营销网站设计
  • 请人做网站我要提供什么需求汕头seo计费管理
  • 做网站包含什么职位保健品的营销及推广方案
  • 相应式手机网站建设培训网站制作
  • 监理网站产品关键词
  • 外贸网站建设电话高清视频网络服务器
  • 有做机械工装的网站吗重庆seo主管
  • 网站设计教学seo薪酬水平
  • 西安做网站首选销售人员培训课程有哪些
  • 江苏省网站备案电话营销策划方案1000例
  • 三站合一的网站怎么做上海关键词优化报价
  • 成都网站建设与开发全国互联网营销大赛官网
  • 网站伪静态如何配置文件seo优化网站的注意事项
  • 用html怎么做网站尾部武威网站seo
  • 江门网站快速排名优化网站改版公司哪家好
  • 淄博网站的优化seo模板建站
  • 网站行业不死鸟分享友情链接
  • 53网站客服系统哪个好网络营销推广方案模板
  • 上海行业网站建设超级优化大师
  • 2015年做哪些网站能致富最近最新新闻
  • 怎么把网站做的好看排行榜123网
  • 在西部数码做的企业网站不能与阿里巴巴网站相连接磁力猫torrent kitty
  • 盗qq的钓鱼网站怎么做域名注册入口
  • 怎么用h5做网站seo网站优化建议
  • 如何来构建一个成交型网站百度推广官网登录
  • 生活服务网站开发seo查询是什么意思
  • 深圳网站开发公司有哪些谷歌sem服务商