Silverlight Measure Method not working properly depending of databound object?
UPDATE II Problem was solved. Thank you.
For a simple Silverlight printing preview engine, my XAML looks like this (excerpt):
<Grid>
<TextBlock Text="{Binding IntroText}" />
<ItemsControl ItemsSource="{Binding DataItems}"
x:Name="DataItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
TextWrapping="Wrap"
Margin="0,2" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="{Binding OutroText}" />
</Grid>
I want to ensure that everything fits on a page, therefore i have a simple method:
public bool FitsOnPrintPage(Size pageDimensions)
{
Measure(new Size(pageDimensions.Width, Double.PositiveInfinity));
return
DesiredSize.Height <= pageDimensions.Height &&
DesiredSize.Width <= pageDimensions.Width;
}
Now we have a strange problem here which I can't explain:
The bound collection DataItems
is a generic object
List. When containing simple strings, the Measure(...)
method works as expected and returns a properly calculated DesiredSize
. So far, everything is working.
However, when having a simple object like this...
public class DataItem
{
public string Value1 { get; set; }
public string Value2 { get; set; }
}
...and changing the TextBlock Binding to <TextBlock Text="{Binding Path=Value1}"...
the resulting view is identical, however the Measure(...)
method doesn't return the expected values, the height of the Items is always zero. Also not working: keep Text Binding and override DataItem
s ToString()
method. View working, Measure doesn't.
I was then trying to force a recalculation using methods like InvalidateMeasure()
or UpdateLayout()
on the DataTemplate or the whole page, without success.
Can you explain this?
UPDATE
Interesting: I've attached a simple customValueConverter
to the T开发者_开发问答extBlock's Binding just for debugging reasons. When a string
object is bound, I can see that Measure(...)
is triggering the Binding - it's resolved first (i can see the debugger stepping into the ValueConverter) and measured afterwards. But when binding a custom class as described above, Measure(...)
doesn't touch the Binding, i am stepping into the ValueConverter
s breakpoint "later". (Have to find out, when exactly)
Does this help you in any kind?
The answer is simple.. you working not in the 'silverlight way'
In Silverligth - it dosen't mather if string fits to the screen width or not, if string dosen't fit, just set TextBlock.Wrap
to Wrap
...
You have problem with this becose of 'old way of thinking'...
But if you want it so much try this:
var ContainerGrid = new Grid(); // create grid at runtime
// !!! it's important for controlToMesure.Parent property to be NULL, if it's not
// !!! then temporary remove controlToMesure from parent container...
ContainerGrid.Children.Add(controlToMesure); // add control that you want to mesure
ContainerGrid.Measure(new Size(pageWidth, pageHeight));
ContainerGrid.Arrange(new Rect(0, 0, pageWidth, pageHeight));
ContainerGrid.UpdateLayout();
var size = ((FrameworkElement)ContainerGrid.Children[0]).DesiredSize;
Here is the code from http://silverpdf.codeplex.com/
Maybee it would help you, but you have to modify it, to make it usable.
private System.Windows.Size CalculeteSize()
{
var s = new System.Windows.Controls.StackPanel()
{
VerticalAlignment = System.Windows.VerticalAlignment.Center,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center
};
var fs = FontPool.GetFontStream(Typeface.FontFamily.Source);
s.Children.Add(new System.Windows.Controls.TextBlock
{
Text = Text,
FontSource = new FontSource(fs),
FontSize = EmSize,
FontFamily = Typeface.FontFamily,
FontStretch = Typeface.FontStretch,
FontStyle = Typeface.FontStyle,
FontWeight = Typeface.FontWeight,
});
s.Measure(new System.Windows.Size(double.MaxValue, double.MaxValue));
var aw = s.DesiredSize.Width;
var ah = s.DesiredSize.Height;
var size = new System.Windows.Size(aw, ah);
return size;
}
Solved
the problem was that the page controls were created and calculated first, and added to the displaying control after generation, because i wanted to avoid frequent UI updates. Something similar was even suggested by Ai_boy, who was trying to solve the problem by using an independent Grid
Control - unfortunately this turned out as a misleading approach. Only after the generated page control was added to the visual tree, it automatically resolves the Bindings resulting in a proper size measuring.
Hope this helps anyone.
精彩评论