开发者

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 DataItems 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 custom ValueConverter 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 ValueConverters 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜