翼度科技»论坛 编程开发 .net 查看内容

wpf 如何7步写一个badge控件

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
首先看一下效果:

 任意控件可以附加一个文字在控件的右上角,并带有红色背景
第一步,新建一个空的wpf项目:
第二步,创建一个类,取名为badge:
第三步,将badge的父类设置成  System.Windows.Documents.Adorner
  1.     public class Badge : Adorner
  2.     {
  3.         public Badge(UIElement adornedElement) : base(adornedElement)
  4.         {
  5.         }
  6.     }
复制代码
里面的adornedElement表示badge后面附加的对象
关于Adorner这个类的说明,微软给了相应的教程     https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/controls/adorners-overview?view=netframeworkdesktop-4.8
也可以F11查看Adorner类的说明.
 
第4步,给badge添加一个Content的附加属性:
  1.         public static readonly DependencyProperty ContentProperty;
  2.         static Badge()
  3.         {
  4.             ContentProperty = DependencyProperty.RegisterAttached("Content", typeof(string), typeof(Badge),
  5.                 new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(ContentChangedCallBack)));
  6.         }<br>
复制代码
      public static string GetContent(DependencyObject obj)
              {
                      return (string)obj.GetValue(ContentProperty);
              }
  1. [/code]       public static void SetContent(DependencyObject obj, string value)
  2.               {
  3.                       obj.SetValue(ContentProperty, value);
  4.               }
  5. 第5步,实现content的回调方法:
  6. [code]private static void ContentChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
  7. {
  8.     var target = d as FrameworkElement;
  9.     if (target != null)
  10.     {
  11.         if (target.IsLoaded)
  12.         {
  13.             var layer = AdornerLayer.GetAdornerLayer(target);
  14.             if (layer != null)
  15.             {
  16.                 var Adorners = layer.GetAdorners(target);
  17.                 if (Adorners != null)
  18.                 {
  19.                     foreach (var adorner in Adorners)
  20.                     {
  21.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  22.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  23.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  24.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  25.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  26.     </StackPanel>if (adorner is Badge)
  27.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  28.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  29.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  30.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  31.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  32.     </StackPanel>{
  33.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  34.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  35.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  36.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  37.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  38.     </StackPanel>    layer.Remove(adorner);
  39.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  40.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  41.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  42.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  43.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  44.     </StackPanel>}
  45.                     }
  46.                 }
  47.                 layer.Add(new Badge(target));
  48.             }
  49.         }
  50.         else
  51.         {
  52.             target.Loaded += (sender, ae) =>
  53.             {
  54.                 var layer = AdornerLayer.GetAdornerLayer(target);
  55.                 if (layer != null)
  56.                 {
  57.                     var Adorners = layer.GetAdorners(target);
  58.                     if (Adorners != null)
  59.                     {
  60.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  61.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  62.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  63.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  64.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  65.     </StackPanel>foreach (var adorner in Adorners)
  66.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  67.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  68.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  69.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  70.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  71.     </StackPanel>{
  72.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  73.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  74.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  75.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  76.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  77.     </StackPanel>    if (adorner is Badge)
  78.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  79.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  80.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  81.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  82.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  83.     </StackPanel>    {
  84.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  85.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  86.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  87.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  88.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  89.     </StackPanel>        layer.Remove(adorner);
  90.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  91.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  92.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  93.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  94.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  95.     </StackPanel>    }
  96.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  97.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  98.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  99.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  100.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  101.     </StackPanel>}
  102.                     }
  103.                     layer.Add(new Badge(target));
  104.                 }
  105.             };
  106.         }
  107.     }
  108. }
复制代码
第6步,重写一下OnRender方法:
  1.         protected override void OnRender(DrawingContext drawingContext)
  2.         {
  3.             var element = this.AdornedElement as FrameworkElement;
  4.             Rect adornedElementRect = new Rect(element.DesiredSize);
  5.             var point = adornedElementRect.TopRight;
  6.             point.X = adornedElementRect.Right - element.Margin.Left - element.Margin.Right;
  7.             SolidColorBrush renderBrush = new SolidColorBrush(Colors.Red);
  8.             Pen renderPen = new Pen(new SolidColorBrush(Colors.Red), 0.5);
  9.             double renderRadius = 5;
  10.             var content = this.AdornedElement.GetValue(Badge.ContentProperty).ToString();
  11.             FormattedText formattedText = new FormattedText(content, CultureInfo.GetCultureInfo("zh-cn"), FlowDirection.LeftToRight, new Typeface("Verdana"), 10, Brushes.White);
  12.             var textWidth = formattedText.Width;
  13.             var textHeight = formattedText.Height;
  14.             var rectangleSizeWidth = textWidth < 15 ? 15 : textWidth;
  15.             var rectangleSizeHeight = textHeight < 15 ? 15 : textHeight;
  16.             var size = new Size(rectangleSizeWidth, rectangleSizeHeight);
  17.             Rect rect = new Rect(new Point(point.X - rectangleSizeWidth / 2, point.Y - rectangleSizeHeight / 2), size);
  18.             drawingContext.DrawRoundedRectangle(renderBrush, renderPen, rect, renderRadius, renderRadius);
  19.             drawingContext.DrawText(formattedText, new Point(point.X - textWidth / 2, point.Y - textHeight / 2));
  20.         }
复制代码
这段代码就是在目标控件的右上角绘制一个带圆角的rectangle,背景色为红色,再绘制一个文本用来显示content.
第7步,运用到项目中:
  1.     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
  2.         <cc:CornerButton ButtonType="OutLine" Width="200" Height="30"
  3.                          cc:Badge.Content="{Binding ElementName=textbox1, Path=Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/>
  4.         <cc:CornerTextBox x:Name="textbox1" Width="200" Height="30" Text="12"
  5.                           VerticalContentAlignment="Center" WaterText="BadgeContent"/>
  6.     </StackPanel>
复制代码
cc是表示badge所在的命名空间,然后你就会发现,你改变textbox的值的时候,badge会跟着textbox的值发生变化哦.
 
项目github地址:bearhanQ/WPFFramework: Share some experience (github.com)
QQ技术交流群:332035933;
 

来源:https://www.cnblogs.com/lvpp13/p/18354811
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具