WPF C#仿ios 安卓 红点消息提示
先把效果贴出来,大家看看。
代码下载地址:
http://download.csdn.net/detail/candyvoice/9730751
点击+,按钮上的红点提示会增加1,点击-,按钮上的红点提示会减去1;点击E,显示或者隐藏红点提示。
这里主要利用了自定义装饰件(Adorner)。
参考的主要文章是下面这个文章,这里由于我只需要在自己已有的button上添加一个红点提示,所以精简了下面的内容。
http://blog.csdn.net/kongxh_1981/article/details/48955693
我的理解是,PromptAdorner(继承Adroner)管理PromptChrome(继承Control)。说白了就是PromptAdorner负责装饰,装饰些什么东西则交给PromptChrome来完成。
具体的理论请参考下面
http://blog.csdn.net/kongxh_1981/article/details/48955497
说一下具体的做法。
首先添加PromptChrome.cs和PromptAdorner.cs。代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApplication2
{
internal class PromptChrome : Control
{
static PromptChrome()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PromptChrome), new FrameworkPropertyMetadata(typeof(PromptChrome)));
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
this.Width = 25;
this.Height = 25;
this.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
this.VerticalAlignment = System.Windows.VerticalAlignment.Top;
TranslateTransform tt = new TranslateTransform();
tt.X = 5;
tt.Y = 5;
this.RenderTransform = tt;
return base.ArrangeOverride(arrangeBounds);
}
}
}
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 WpfApplication2
{
public class PromptAdorner : Adorner
{
public static readonly DependencyProperty PromptCountProperty =
DependencyProperty.RegisterAttached("PromptCount", typeof(int), typeof(PromptAdorner),
new FrameworkPropertyMetadata(0, new PropertyChangedCallback(PromptCountChangedCallBack), new CoerceValueCallback(CoercePromptCountCallback)));
public static int GetPromptCount(DependencyObject obj)
{
return (int)obj.GetValue(PromptCountProperty);
}
public static void SetPromptCount(DependencyObject obj, int value)
{
obj.SetValue(PromptCountProperty, value);
}
public static readonly DependencyProperty IsPromptEnabledProperty =
DependencyProperty.RegisterAttached("IsPromptEnabled", typeof(bool), typeof(PromptAdorner),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(IsPromptEnabledChangedCallBack), null));
public static bool GetIsPromptEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsPromptEnabledProperty);
}
public static void SetIsPromptEnabled(DependencyObject obj, bool value)
{
obj.SetValue(IsPromptEnabledProperty, value);
}
private static object CoercePromptCountCallback(DependencyObject d, object value)
{
int promptCount = (int)value;
promptCount = Math.Max(0, promptCount);
return promptCount;
}
public static void PromptCountChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
public static void IsPromptEnabledChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var source = d as FrameworkElement;
bool isEnabled = (bool)e.NewValue;
if (isEnabled)
{
//装饰件可用,添加装饰件
AdornerLayer layer = AdornerLayer.GetAdornerLayer(source);
if (layer != null)
{
//能够获取装饰层,说明已经load过了,直接生成装饰件
var adorner = new PromptAdorner(source);
layer.Add(adorner);
}
else
{
//layer为null,说明还未load过(整个可视化树中没有装饰层的情况不考虑)
//在控件的loaded事件内生成装饰件
source.Loaded += (s1, e1) =>
{
var adorner = new PromptAdorner(source);
AdornerLayer.GetAdornerLayer(source).Add(adorner);
};
}
}
else
{
//装饰件不可用,移除装饰件
AdornerLayer layer = AdornerLayer.GetAdornerLayer(source);
if (layer != null)
{
Adorner[] AllAdorners = layer.GetAdorners(source);
if (AllAdorners != null)
{
IEnumerable<Adorner> desAdorners = AllAdorners.Where(p => p is PromptAdorner);
if (desAdorners != null && desAdorners.Count() > 0)
{
desAdorners.ToList().ForEach(p => layer.Remove(p));
}
}
}
}
}
protected override int VisualChildrenCount
{
get { return 1; }
}
public PromptAdorner(UIElement adornedElement)
: base(adornedElement)
{
_chrome = new PromptChrome();
_chrome.DataContext = adornedElement;
this.AddVisualChild(_chrome);
}
protected override Visual GetVisualChild(int index)
{
return _chrome;
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
_chrome.Arrange(new Rect(arrangeBounds));
return arrangeBounds;
}
PromptChrome _chrome;
}
}
2 添加好之后,先编译一下程序,再 在MainWindow里拖上三个button,先拖一个PromptChrome控件到窗口的任意位置
新建一个Themes文件夹,添加资源词典,Generic.xaml
定义样式PromptChrome,Generic.xaml具体代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2">
<Style TargetType="{x:Type local:PromptChrome}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PromptChrome}">
<Grid x:Name="container">
<!--最外圈的白色圆框,并对其作阴影效果-->
<!--<Ellipse Fill="White">
<Ellipse.Effect>
<DropShadowEffect BlurRadius="6"
ShadowDepth="6"
Opacity="0.8"
Direction="270"
RenderingBias="Performance"/>
</Ellipse.Effect>
</Ellipse>-->
<!--内部的上半圆-->
<Ellipse Margin="3">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFF4AEB1"/>
<GradientStop Offset="0.5" Color="#FFE3313A"/>
<GradientStop Offset="1" Color="#FFE3313A"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--内部的下半圆,通过采用Exclude模式合并上下两个圆来完成-->
<Path HorizontalAlignment="Center" VerticalAlignment="Center">
<Path.Data>
<CombinedGeometry GeometryCombineMode="Exclude" >
<CombinedGeometry.Geometry1>
<EllipseGeometry Center="7 7" RadiusX="7" RadiusY="7" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry Center="7 0" RadiusX="9" RadiusY="7"/>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
<Path.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFDF151F"/>
<GradientStop Offset="1" Color="#FFBA0004"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Viewbox Stretch="Uniform" >
<!--绑定上文中的PromptCount属性-->
<Label Content="{Binding Path=(local:PromptAdorner.PromptCount)}"
x:Name="label"
Foreground="White"
FontWeight="Bold"
FontSize="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Viewbox>
</Grid>
<ControlTemplate.Triggers>
<!--使用数据触发器,当PromptCount为0时,隐藏提示-->
<DataTrigger Binding="{Binding Path=(local:PromptAdorner.PromptCount)}" Value="0">
<Setter TargetName="container" Property="Visibility" Value="Hidden"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
3编辑MainWindow.xaml中的代码
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="button" Content="按钮" HorizontalAlignment="Left" Margin="209,67,0,0" VerticalAlignment="Top" Width="75"
local:PromptAdorner.IsPromptEnabled="True"
local:PromptAdorner.PromptCount="0" Click="button_Click" IsHitTestVisible="True"/>
<Button x:Name="button1" Content="+" HorizontalAlignment="Left" Margin="89,201,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
<Button x:Name="button2" Content="-" HorizontalAlignment="Left" Margin="214,202,0,0" VerticalAlignment="Top" Width="75" Click="button2_Click"/>
<Button x:Name="button3" Content="E" HorizontalAlignment="Left" Margin="339,202,0,0" VerticalAlignment="Top" Width="75" Click="button3_Click"/>
</Grid>
</Window>
实现+、-、E按钮的作用,MainWindow.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;
namespace WpfApplication2
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
int promptCount = (int)button.GetValue(PromptAdorner.PromptCountProperty);
button.SetValue(PromptAdorner.PromptCountProperty, ++promptCount);
}
private void button2_Click(object sender, RoutedEventArgs e)
{
int promptCount = (int)button.GetValue(PromptAdorner.PromptCountProperty);
button.SetValue(PromptAdorner.PromptCountProperty, --promptCount);
}
private void button3_Click(object sender, RoutedEventArgs e)
{
bool isEnable = (bool)button.GetValue(PromptAdorner.IsPromptEnabledProperty);
button.SetValue(PromptAdorner.IsPromptEnabledProperty, !isEnable);
}
private void button_Click(object sender, RoutedEventArgs e)
{
}
}
}
编译通过后,删掉之前拖动到窗口任意位置的PromptChrome控件,再次编译通过,就可以实现在普通的button上添加红点提示信息。
中间犯过几个错误,就是在编辑Generic.xaml的时候,总是出现Binding="{Binding Path=(local:PromptAdorner.PromptCount)}无法找到的情况,这里应该是先拖一个自定义PromptChrome控件到窗口,后面删掉即可。
代码下载地址:
http://download.csdn.net/detail/candyvoice/9730751
WPF C#仿ios 安卓 红点消息提示的更多相关文章
- wpf实现仿qq消息提示框
原文:wpf实现仿qq消息提示框 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/huangli321456/article/details/5052 ...
- 【WPF】屏幕右下角消息提示框
WPF做一个仿QQ的右下角消息提示窗,网上找到几个Demo后,选了一个比较好用的. 博客 http://blog.csdn.net/huangli321456/article/details/5052 ...
- (转载) Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框
Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框 标签: Android清除功能EditText仿IOS的输入框 2013-09-04 17:33 70865人阅读 ...
- react-native自定义Modal模态框|仿ios、微信弹窗RN版
前序 纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验.如:微信.支付宝.ios都有很成熟的一套弹窗UI展示场景. 最近一直沉迷在rea ...
- SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)
SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...
- 自定义iOS 中推送消息 提示框
看到标题你可能会觉得奇怪 推送消息提示框不是系统自己弹出来的吗? 为什么还要自己自定义呢? 因为项目需求是这样的:最近需要做 远程推送通知 和一个客服系统 包括店铺客服和官方客服两个模块 如果有新的消 ...
- Html - 仿Ios assistiveTouch 悬浮辅助球工具
仿Ios assistiveTouch 悬浮辅助球工具 <!DOCTYPE html> <html> <head> <meta charset="u ...
- Android仿IOS回弹效果 ScrollView回弹 总结
Android仿IOS回弹效果 ScrollView回弹 总结 应项目中的需求 须要仿IOS 下拉回弹的效果 , 我在网上搜了非常多 大多数都是拿scrollview 改吧改吧 试了一些 发现总 ...
- Ion-affix & Ion-stick 仿IOS悬浮列表插件
Ion-affix & Ion-stick 仿IOS悬浮列表插件 Ion-affix 1.相关网页 Ion-affix 2.环境准备: 执行命令 bower install ion-affix ...
随机推荐
- ArcGIS Arcade
ArcGIS Arcade http://127.0.0.1/Resource/JavaScript/arcgis_js_api/sdk/4.10/latest/guide/arcade/index. ...
- 编写xml文件不当时会出现R文件找不到情况
1,先检查xml文件是否报错,报错的话直接找到报错行. 2,xml文件若不报错,可能是文本值得格式输入错误 比如android:text=“<0.5km”,此时的小于号就会引发错误,导致R文件找 ...
- Android View体系(八)从源码解析View的layout和draw流程
前言 上一篇文章我们讲了View的measure的流程,接下来我们讲下View的layout和draw流程,如果你理解了View的measure的流程,那这篇文章自然就不在话下了. 1.View的la ...
- (网页)HTML小技巧的一些小技巧
转自CSDN: 1.怎样定义网页语言(字符集)? 在制作网页过程中,你首先要定义网页语言,以便访问者浏览器自动设置语言,而我们用所见即所得的HTML工具时,都没有注意到这个问题, ...
- 一种快速部署开发用oracle的办法
前段时间工作中需要在不少开发环境中快速提供开发可用的oracle环境,由于一一培训并部署原生oracle人力和时间成本过高,后来使用docker版本oracle,大大方便了开发工作的快速启动,方法记录 ...
- [20171214]hashcat破解oracle口令.txt
[20171214]hashcat破解oracle口令.txt hashcat is the world's fastest and most advanced password recovery u ...
- SQL Server 临时表和表变量系列之选择篇
原文地址:https://yq.aliyun.com/articles/69187 摘要: # 摘要 通过前面的三篇系列文章,我们对临时表和表变量的概念.对比和认知误区已经有了非常全面的认识.其实,我 ...
- SQL SERVER2008判断文件夹是否存在并创建文件夹
原文地址:https://www.cnblogs.com/iiwen/p/7650118.html DECLARE @PATH VARCHAR(255) --路径 DECLARE @DATE VARC ...
- Intel P4 CPU
1. P4 CPU 结构 奔4处理器是Intel的经典之作,它是采用乱序执行内核的超标量处理器.P4采用的微架构称为 Net Burst,基本结构如下: 奔4处理器微架构被分成了4大部分: (1)存储 ...
- 基于python的快速傅里叶变换FFT(二)
基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点 FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...