在最小值和最大值之间进行缩放(视觉效果)(例如,等级条)






4.82/5 (3投票s)
如果你需要某种等级条/仪表,请看一看!

引言
在许多与过程自动化相关的项目中,需要以视觉方式显示设备和当前状态。 许多设备,例如储罐,都有某种仪表,应该显示范围内的当前值(最小值/最大值)。 让我们看看如何使用 WPF Viewbox
和一些简单的计算以动态方式实现这一点。
结构
对于这个例子,我使用了以下结构
- 上面看到的图像是一个渲染后的 WPF
UserControl
,应该代表一个储罐。 它执行以下操作- 它具有用于最小值和最大值参数以及当前液位的代码隐藏属性。
- 还有一个属性,将当前液位从最小值/最大值缩放到 0/1(即 0...100%)。
- 该控件在应用程序的主窗口中多次实例化。
设备用户控件
首先,让我们看一下 XAML
<UserControl x:Class="Technewlogic.Samples.MinMaxScaling.Equipment"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:Technewlogic.Samples.MinMaxScaling"
x:Name="me">
<Grid Margin="5" DataContext="{Binding ElementName=me}">
<Rectangle x:Name="backgroundRect" Fill="LightGray"
Stroke="DarkGray" StrokeThickness="2"
RadiusX="5" RadiusY="5" />
<DockPanel LastChildFill="True" Margin="5">
<!-- Enter Data Section -->
<Grid Margin="3" DockPanel.Dock="Left">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Top"
HorizontalAlignment="Right">
<TextBlock Text="Max Level:" Margin="2"
VerticalAlignment="Center" />
<TextBox Text="{Binding Max, UpdateSourceTrigger=PropertyChanged}"
Width="30" Margin="2" />
</StackPanel>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Right">
<TextBlock Text="Current Level:" FontWeight="Bold"
Margin="2" VerticalAlignment="Center" />
<TextBox Text="{Binding CurrentLevel,
UpdateSourceTrigger=PropertyChanged}"
Width="30" Margin="2" />
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom"
HorizontalAlignment="Right">
<TextBlock Text="Min Level:" Margin="2"
VerticalAlignment="Center" />
<TextBox Text="{Binding Min, UpdateSourceTrigger=PropertyChanged}"
Width="30" Margin="2" />
</StackPanel>
</Grid>
<!-- Level Section -->
<Border x:Name="LevelSection" CornerRadius="3"
BorderBrush="DarkGray" Background="Gray"
BorderThickness="1" Margin="3">
<Viewbox Stretch="Fill">
<StackPanel Orientation="Horizontal">
<Rectangle Fill="Red" Height="1" Width="0" />
<Rectangle Fill="Blue" Width="1"
VerticalAlignment="Bottom" Height="{Binding ScaledValue}" />
</StackPanel>
</Viewbox>
</Border>
</DockPanel>
</Grid>
</UserControl>
很简单!
在“输入数据部分”,我们只是将一些文本框绑定到控件的 Min
、Max
和 CurrentLevel
属性,以便我们可以玩弄这些值并查看会发生什么。
让我们看看“液位部分”中会发生什么:这里,我们有一个边框,它是其父级 DockPanel
的最后一个元素,这意味着该边框完全填充了 DockPanel
的剩余空间。 在边框内部,我们有一个 Viewbox
,应该将其内容拉伸以填充剩余空间(换句话说,Viewbox
的内容应该覆盖我们的 UserControl
的完整剩余空间)。
我们想要实现的是液位表具有深灰色背景(来自边框),然后有一个蓝色条显示缩放后的值。

诀窍是在 Viewbox
内部将所有内容限制为 1(Height
和 Width
),以便在 Viewbox
内部具有“逻辑”或“标准化”大小。 有一个不可见的 Rectangle
,其 Height
= 1,用于限制高度,以及我们的蓝色液位 Rectangle
,其 Width
= 1(用于限制宽度)。 然后,Viewbox
将所有内容缩放到“真实”大小。
剩下的唯一问题是用户控件的代码隐藏中的缩放。
private double _min = 0d;
public double Min
{
get { return _min; }
set
{
_min = value;
OnPropertyChanged("Min");
OnPropertyChanged("ScaledValue");
}
}
private double _max = 100d;
public double Max
{
get { return _max; }
set
{
_max = value;
OnPropertyChanged("Max");
OnPropertyChanged("ScaledValue");
}
}
private double _currentLevel = default(double);
public double CurrentLevel
{
get { return _currentLevel; }
set
{
_currentLevel = value;
OnPropertyChanged("CurrentLevel");
OnPropertyChanged("ScaledValue");
}
}
public double ScaledValue
{
get
{
var scaledValue = CurrentLevel / (Max - Min) - (Min / (Max - Min));
return scaledValue;
}
}
请注意,每次 Min
、Max
或 CurrentLevel
发生变化时,我们还会通知 ScaledValue
发生了变化,因为该属性取决于这些属性。 在数学上,我们从 Min
/ Max
归一化到 0 / 1

就是这样!