ProgressBar符合progressBar值的wirh标签

时间:2015-10-07 20:15:31

标签: wpf progress-bar

我想实现这样的事情:

enter image description here

所以我有ProgreeBar

<ProgressBar
    Name="progressBar1"
    Value="0"
    Height="33"
    Width="300"
    Foreground="SkyBlue"
    HorizontalAlignment="Center"             
    VerticalAlignment="Center"
    Margin="0,220,0,0"/>

GridEllipseTextBlock

<Grid Name="myGrid" Margin="0,100,0,0">
    <Ellipse
        Name="ellipse"
        Width="65"
        Height="65"
        HorizontalAlignment="Center"             
        VerticalAlignment="Center"
        Stroke="SkyBlue"
        Fill="SkyBlue"
        Margin="-300,0,0,0" />
    <TextBlock
        Text="{Binding ElementName=progressBar1, Path=Value}"
        Foreground="White"
        HorizontalAlignment="Center"             
        VerticalAlignment="Center"
        FontSize="16"
        Margin="-300,0,0,0" />
</Grid>

所以这就是结果:

enter image description here

现在每1秒我想增加ProgreeBar value,我正在使用计时器:

void timer_Tick(object sender, EventArgs e)
{
    progressBar1.Value += 4;
    myGrid.Margin = new Thickness((progressBar1.Value * 3 * 2), 100, 0, 0);
}

所以这很好用:

enter image description here

但在某些时候,这个Ellipse超出了正确的位置:

enter image description here

  • 修改

我很高兴在这里采用另一种方法来实现它。

1 个答案:

答案 0 :(得分:1)

它无法正常工作,因为您正在更改Margin,当您将Window调整为较小的值时,它会按照您的要求执行操作。您要做的是使用RenderTransform并指定相对于您希望的坐标的XY坐标。它将与布局无关。

这是我将如何做到的,(可以有改进),但这个想法就在那里。

 progressBar1.Value += 4;
 var grid = VisualTreeHelper.GetChild(progressBar1, 0) as Grid;
 if (grid != null)
 {
   var decorator = grid.Children.OfType<FrameworkElement>().FirstOrDefault(x => x.Name == "PART_Indicator");
   if (decorator != null)
      myGrid.RenderTransform = new TranslateTransform(decorator.ActualWidth, myGrid.RenderTransform.Value.OffsetY);
 }

我做的是想在ProgressBar内获得控件的实际宽度。我怎么知道的?我使用Snoop工具来了解子控件是什么。在那里,我想访问包含为进度条着色的Grid的{​​{1}}的实际值,然后将Rectangle设置为它X 。现在这可行,因为这假设ActualWidthProgressBar只是Ellipse的子控件,我知道它是MainWindow

如果我的控件不是我期望的centered那么你需要通过转换相对于你想要的Visual的点来做更多的工作。可以找到更多信息here

完整代码:

Points