WPF C#仿ios 安卓 红点消息提示

先把效果贴出来,大家看看。

代码下载地址:

http://download.csdn.net/detail/candyvoice/9730751


WPF C#仿ios 安卓 红点消息提示_第1张图片

点击+,按钮上的红点提示会增加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 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

WPF C#仿ios 安卓 红点消息提示_第2张图片

定义样式PromptChrome,Generic.xaml具体代码如下:



    


3编辑MainWindow.xaml中的代码


    
        

实现+、-、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
{
    /// 
    /// MainWindow.xaml 的交互逻辑
    /// 
    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

你可能感兴趣的:(c#,wpf,ios,android,红点提示)