Dobrý den, je to způsobené tím, že velikost Canvasu nezávisí na velikosti elementů, které v něm jsou obsaženy. Velikost Canvasu závisí pouze na elementu, uvnitř kterého je umístěn. Pokud je canvas umístěn uvnitř ViewBoxu (nebo jiného elementu, který je schopen svým potomkům nabídnout "nekonečnou" plochu - např ScrollViewer), je velikost Canvasu 0;0 a jeho potomci jsou vykresleny mimo jeho plochu. Teď ta složitější část, jak to vyřešit :) Nenapadá mě žádné jednoduché řešení na "jeden řádek". 1) Napsat si vlastní Canvas, který bude řešit celý váš probléme, tedy bod 0,0 bude vykreslovat uprostřed plochy a automaticky bude měnit měřítko jako Viewbox. Není to složité, ale je potřeba znát, jak funguje WPF a jak přetížit MeasureOverride a ArrangeOverride. 2) Při každé změně elementů uvnitř Canvasu spočítat, jak velký je potřeba Canvas, aby se do něj všechno vešlo a tuto velikost nastavit jako rozměry canvasu. Canvas pak umístit do Viewboxu. Canvas už pak nebude mít nulovou velikost a Viewbox bude umět vypočítat měřítko.
private void CalculateCanvasSize()
{
double maxX = 0;
double maxY = 0;
foreach (FrameworkElement element in canvas.Children)
{
//zjistit hodnoty pro element
var left = Canvas.GetLeft(element);
var right = Canvas.GetRight(element);
var top = Canvas.GetTop(element);
var bottom = Canvas.GetBottom(element);
//vypočítat hranice objektu
if (double.IsNaN(left) == false)
right = left + element.ActualWidth;
else if (double.IsNaN(right) == false)
throw new NotSupportedException();
else { left = 0; right = element.ActualWidth; }
if (double.IsNaN(top) == false)
bottom = top + element.ActualHeight;
else if (double.IsNaN(bottom) == false)
throw new NotSupportedException();
else { top = 0; bottom = element.ActualHeight; }
//uložit největší vzdálenost od bodu 0;0
maxX = Math.Max(maxX, Math.Max(Math.Abs(left), Math.Abs(right)));
maxY = Math.Max(maxY, Math.Max(Math.Abs(top), Math.Abs(bottom)));
}
//nastavit canvas na dvojnásobek maximální vzdálenost (dvojnásobek, jde se na obě strany)
canvas.Width = 2 * maxX;
canvas.Height = 2 * maxY;
//souřadnice objektů v canvasu jsou vzhledem k levémmu hornímu rohu => změnou velikosti canvasu se posune jeho levý horní roh => je třeba posunout objekty v canvasu
canvas.RenderTransform = new TranslateTransform(maxX, maxY);
}
Pro úplnost přikládám i XAML
<Grid>
<Viewbox>
<Canvas Name="canvas"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Rectangle Width="50" Height="50" Canvas.Left="-25" Canvas.Top="-25" Stroke="Black" StrokeThickness="5" />
<Rectangle Width="100" Height="100" Canvas.Left="25" Canvas.Top="25" Stroke="Red" StrokeThickness="5" />
<Rectangle Width="1000" Height="10" Stroke="Red" />
<Rectangle Width="90" Height="10" Canvas.Left="10" Canvas.Top="50" Stroke="Blue" />
</Canvas>
</Viewbox>
</Grid>
|