实战需求
在称量过程中,显示实时重量。且可以直观体现“接近量”、“目标量”、“超过量”。
控件最终效果如下图所示。
蓝色表示接近量、绿色表示目标量、红色表示超过量。
话不多说,下面展示源码,有问题的在留言区留言,我会及时回复.
控件模板前台定义RProgress.xaml如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFCustomControl.Controls">
<!--游标偏移转换-->
<local:CursorOffsetConverter x:Key="cursorOffsetConverter" />
<!--进度条宽度转换-->
<local:ProgressWidthConverter x:Key="progressWidthConverter" />
<!--游标样式-->
<Style x:Key="CursorStyle" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Grid HorizontalAlignment="Right" >
<Path Stroke="{TemplateBinding Background}" StrokeThickness="1" Fill="{TemplateBinding Background}" Stretch="Uniform" HorizontalAlignment="Right" VerticalAlignment="Top" Width="20" Height="10"
Data="M0,0 L1,-1 L-1,-1 z" SnapsToDevicePixels="True" />
<Path Stroke="{TemplateBinding Background}" StrokeThickness="1" Fill="{TemplateBinding Background}" Stretch="Uniform" HorizontalAlignment="Center"
Data="M0,0 L0,4" SnapsToDevicePixels="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="RProgress_Template" TargetType="local:RProgress">
<Grid ClipToBounds="True">
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="1" SnapsToDevicePixels="True" BorderBrush="#C2C2C2" BorderThickness="1" />
<Border Grid.Row="1" SnapsToDevicePixels="True" Background="SkyBlue" Margin="1" x:Name="progress" HorizontalAlignment="Left">
<Border.Width>
<MultiBinding Converter="{StaticResource progressWidthConverter}">
<Binding Path="Value" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
<Binding Path="High" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
</MultiBinding>
</Border.Width>
</Border>
<TextBlock Grid.Row="1" Text="{TemplateBinding Text}" VerticalAlignment="Center" Margin="10 0"/>
<Grid Grid.RowSpan="2" HorizontalAlignment="Right">
<ContentControl x:Name="cursorLow" Style="{StaticResource CursorStyle}" HorizontalAlignment="Right" Background="Blue" >
<ContentControl.RenderTransform>
<TranslateTransform >
<TranslateTransform.X>
<MultiBinding Converter="{StaticResource cursorOffsetConverter}">
<Binding Path="Low" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
<Binding Path="High" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
</MultiBinding>
</TranslateTransform.X>
</TranslateTransform>
</ContentControl.RenderTransform>
</ContentControl>
<ContentControl x:Name="cursorNormal" Style="{StaticResource CursorStyle}" HorizontalAlignment="Right" Background="Green" >
<ContentControl.RenderTransform>
<TranslateTransform >
<TranslateTransform.X>
<MultiBinding Converter="{StaticResource cursorOffsetConverter}">
<Binding Path="Target" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
<Binding Path="High" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=local:RProgress}" />
</MultiBinding>
</TranslateTransform.X>
</TranslateTransform>
</ContentControl.RenderTransform>
</ContentControl>
<ContentControl x:Name="cursorHigh" Style="{StaticResource CursorStyle}" HorizontalAlignment="Right" Background="Red" />
</Grid>
</Grid>
</ControlTemplate>
</ResourceDictionary>
后台代码cs如下:
public partial class RProgress: RangeBase
{
public const double CursorWidth = 20;
static RProgress()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(RProgress), new FrameworkPropertyMetadata(typeof(RProgress)));
}
#region TextProperty 进度跳上显示的文本
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(RProgress), new PropertyMetadata(""));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
#endregion
#region LowProperty 最小用量
public static readonly DependencyProperty LowProperty =
DependencyProperty.Register("Low", typeof(double), typeof(RProgress), new PropertyMetadata(0d));
public double Low
{
get { return (double)GetValue(LowProperty); }
set { SetValue(LowProperty, value); }
}
#endregion
#region TargetProperty 目标用量
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(double), typeof(RProgress), new PropertyMetadata(0d));
public double Target
{
get { return (double)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
#endregion
#region HighProperty 最大用量
public static readonly DependencyProperty HighProperty =
DependencyProperty.Register("High", typeof(double), typeof(RProgress), new PropertyMetadata(0d));
public double High
{
get { return (double)GetValue(HighProperty); }
set { SetValue(HighProperty, value); }
}
#endregion
#region ValueProperty 当前用量
public new static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(RProgress), new PropertyMetadata(0d));
public new double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
#endregion
}
//游标偏移转换
public class CursorOffsetConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 3 && values[0] is double value && values[1] is double high && values[2] is double width)
{
return high == 0 ? 0 : (value / high - 1) * (width - RProgress.CursorWidth * 0.5);
}
else
{
return -40;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
// 进度值宽度转换
public class ProgressWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 3 && values[0] is double value && values[1] is double high && values[2] is double width)
{
return Math.Min(width-2, Math.Max(0, (width - RProgress.CursorWidth * 0.5) * value / high));
}
else
{
return 0;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
使用控件的代码如下:
<Window x:Class="WPFCustomControl.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:WPFCustomControl"
xmlns:cr="clr-namespace:WPFCustomControl.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<cr:RProgress Template="{StaticResource RProgress_Template}" Margin="10" Height="40"
Value="110"
Low="80" Target="100" High="120"
Text="标量刻度显示"/>
</Grid>
</Window>