原文: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 安卓 红点消息提示的更多相关文章

  1. wpf实现仿qq消息提示框

    原文:wpf实现仿qq消息提示框 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/huangli321456/article/details/5052 ...

  2. 【WPF】屏幕右下角消息提示框

    WPF做一个仿QQ的右下角消息提示窗,网上找到几个Demo后,选了一个比较好用的. 博客 http://blog.csdn.net/huangli321456/article/details/5052 ...

  3. (转载) Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框

    Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框 标签: Android清除功能EditText仿IOS的输入框 2013-09-04 17:33 70865人阅读  ...

  4. react-native自定义Modal模态框|仿ios、微信弹窗RN版

    前序 纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验.如:微信.支付宝.ios都有很成熟的一套弹窗UI展示场景. 最近一直沉迷在rea ...

  5. SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

     SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...

  6. 自定义iOS 中推送消息 提示框

    看到标题你可能会觉得奇怪 推送消息提示框不是系统自己弹出来的吗? 为什么还要自己自定义呢? 因为项目需求是这样的:最近需要做 远程推送通知 和一个客服系统 包括店铺客服和官方客服两个模块 如果有新的消 ...

  7. Html - 仿Ios assistiveTouch 悬浮辅助球工具

    仿Ios assistiveTouch 悬浮辅助球工具 <!DOCTYPE html> <html> <head> <meta charset="u ...

  8. Android仿IOS回弹效果 ScrollView回弹 总结

    Android仿IOS回弹效果  ScrollView回弹 总结 应项目中的需求  须要仿IOS 下拉回弹的效果 , 我在网上搜了非常多 大多数都是拿scrollview 改吧改吧 试了一些  发现总 ...

  9. Ion-affix & Ion-stick 仿IOS悬浮列表插件

    Ion-affix & Ion-stick 仿IOS悬浮列表插件 Ion-affix 1.相关网页 Ion-affix 2.环境准备: 执行命令 bower install ion-affix ...

随机推荐

  1. ArcGIS Arcade

    ArcGIS Arcade http://127.0.0.1/Resource/JavaScript/arcgis_js_api/sdk/4.10/latest/guide/arcade/index. ...

  2. 编写xml文件不当时会出现R文件找不到情况

    1,先检查xml文件是否报错,报错的话直接找到报错行. 2,xml文件若不报错,可能是文本值得格式输入错误 比如android:text=“<0.5km”,此时的小于号就会引发错误,导致R文件找 ...

  3. Android View体系(八)从源码解析View的layout和draw流程

    前言 上一篇文章我们讲了View的measure的流程,接下来我们讲下View的layout和draw流程,如果你理解了View的measure的流程,那这篇文章自然就不在话下了. 1.View的la ...

  4. (网页)HTML小技巧的一些小技巧

    转自CSDN: 1.怎样定义网页语言(字符集)?            在制作网页过程中,你首先要定义网页语言,以便访问者浏览器自动设置语言,而我们用所见即所得的HTML工具时,都没有注意到这个问题, ...

  5. 一种快速部署开发用oracle的办法

    前段时间工作中需要在不少开发环境中快速提供开发可用的oracle环境,由于一一培训并部署原生oracle人力和时间成本过高,后来使用docker版本oracle,大大方便了开发工作的快速启动,方法记录 ...

  6. [20171214]hashcat破解oracle口令.txt

    [20171214]hashcat破解oracle口令.txt hashcat is the world's fastest and most advanced password recovery u ...

  7. SQL Server 临时表和表变量系列之选择篇

    原文地址:https://yq.aliyun.com/articles/69187 摘要: # 摘要 通过前面的三篇系列文章,我们对临时表和表变量的概念.对比和认知误区已经有了非常全面的认识.其实,我 ...

  8. SQL SERVER2008判断文件夹是否存在并创建文件夹

    原文地址:https://www.cnblogs.com/iiwen/p/7650118.html DECLARE @PATH VARCHAR(255) --路径 DECLARE @DATE VARC ...

  9. Intel P4 CPU

    1. P4 CPU 结构 奔4处理器是Intel的经典之作,它是采用乱序执行内核的超标量处理器.P4采用的微架构称为 Net Burst,基本结构如下: 奔4处理器微架构被分成了4大部分: (1)存储 ...

  10. 基于python的快速傅里叶变换FFT(二)

    基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点  FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...