我想实现这样的事情:
所以我有ProgreeBar
:
<ProgressBar
Name="progressBar1"
Value="0"
Height="33"
Width="300"
Foreground="SkyBlue"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,220,0,0"/>
Grid
与Ellipse
和TextBlock
:
<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>
所以这就是结果:
现在每1秒我想增加ProgreeBar
value
,我正在使用计时器:
void timer_Tick(object sender, EventArgs e)
{
progressBar1.Value += 4;
myGrid.Margin = new Thickness((progressBar1.Value * 3 * 2), 100, 0, 0);
}
所以这很好用:
但在某些时候,这个Ellipse
超出了正确的位置:
我很高兴在这里采用另一种方法来实现它。
答案 0 :(得分:1)
它无法正常工作,因为您正在更改Margin
,当您将Window
调整为较小的值时,它会按照您的要求执行操作。您要做的是使用RenderTransform
并指定相对于您希望的坐标的X
和Y
坐标。它将与布局无关。
这是我将如何做到的,(可以有改进),但这个想法就在那里。
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
。现在这可行,因为这假设ActualWidth
和ProgressBar
只是Ellipse
的子控件,我知道它是MainWindow
。
如果我的控件不是我期望的centered
那么你需要通过转换相对于你想要的Visual的点来做更多的工作。可以找到更多信息here。
完整代码:
Points