WPF Adorner

liuyong111發表於2018-07-03

之前做專案時,為了實現類似微信訊息數目的效果

 
image.png

 

,我之前是修改的ControlTemplate。類似於將一個帶數字的控制元件,放在另一個控制元件的右上角,來實現的這個效果。
原來WPF有個Adorner,也可以實現這樣的效果。
WPF中很多控制元件,都帶Adorner層。這相當於一個控制元件的裝飾層。我們在這裡面可以做出很多蠻好的效果。比如錯誤提示等。
我們要實現上圖的那種效果,我們可以做一個附加屬性。

 public static bool GetShowAdorner(DependencyObject obj)
    {
        return (bool)obj.GetValue(ShowAdornerProperty);
    }
    public static void SetShowAdorner(DependencyObject obj, bool value)
    {
        obj.SetValue(ShowAdornerProperty, value);
    }        
    public static readonly DependencyProperty ShowAdornerProperty =
        DependencyProperty.RegisterAttached("ShowAdorner", typeof(bool), typeof(MainWindow), new PropertyMetadata(false, Method));

    private static void Method(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ele = d as Visual;

        var adolay = AdornerLayer.GetAdornerLayer(ele);

        if (adolay != null)
        {
            var ados = adolay.GetAdorners(ele as UIElement);
            if (ados == null)
            {
                adolay.Add(new KDAdorner(ele as UIElement));
            }
            ados = adolay.GetAdorners(ele as UIElement);
            if (ados != null && ados.Count() != 0)
            {
                var ado = ados.FirstOrDefault() as KDAdorner;

                if ((bool)e.NewValue)
                {
                    ado.ShowImage();

                }
                else
                {
                    ado.HideImage();
                }
            }

        }

 

繼承Adorner,實現我們想要的Adorner效果

 public class KDAdorner : Adorner
    {
        private VisualCollection _visuals;
        private Canvas _grid;
        private Border _br;
        public KDAdorner(UIElement ele)
            : base(ele)
        {
            _visuals = new VisualCollection(this);
            _br = new Border ();
            _br.CornerRadius= new CornerRadius (50);
            _br.Background = Brushes.Red;
            TextBlock _txt = new TextBlock();
            _txt.Text = "4";
            _txt.Width=_txt.Height = 20;
            _txt.Foreground = Brushes.White;
            _txt.TextAlignment = TextAlignment.Center;
            _br.Child = _txt;
            _grid = new Canvas();
            _grid.Children.Add(_br);
            _visuals.Add(_grid);
        }
        protected override Visual GetVisualChild(int index)
        {
            return _visuals[index];
        }
        public void ShowImage()
        {
            _grid.Visibility = System.Windows.Visibility.Visible;
        }
        public void HideImage()
        {
            _grid.Visibility = System.Windows.Visibility.Hidden;
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            _grid.Arrange(new Rect(finalSize));
            _br.Margin = new Thickness(finalSize.Width - 12.5, -12.5, 0, 0);
            return base.ArrangeOverride(finalSize);
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return _visuals.Count;
            }
        }
    }

 

VIew中給需要新增Adorner效果的控制元件,新增附加屬性

 

 
image.png

CheckBox繫結了Button的附加屬性,我們可以通過IsChecked,控制Adorner層的顯示,隱藏。

 

 
image.png

相關文章