1

UPDATE II 问题已解决。谢谢你。


对于一个简单的 Silverlight 打印预览引擎,我的 XAML 如下所示(摘录):

<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>

我想确保所有内容都适合页面,因此我有一个简单的方法:

public bool FitsOnPrintPage(Size pageDimensions)
{
    Measure(new Size(pageDimensions.Width, Double.PositiveInfinity));

    return
        DesiredSize.Height <= pageDimensions.Height &&
        DesiredSize.Width <= pageDimensions.Width;
}

现在我们有一个奇怪的问题,我无法解释:

绑定的集合DataItems是一个通用object列表。当包含简单字符串时,该Measure(...)方法按预期工作并返回正确计算的DesiredSize. 到目前为止,一切正常。

然而,当有一个像这样的简单对象时......

public class DataItem
{
    public string Value1 { get; set; }
    public string Value2 { get; set; }
}

...并将 TextBlock Binding 更改<TextBlock Text="{Binding Path=Value1}"...为结果视图是相同的,但是该Measure(...)方法不返回预期值,项目的高度始终为零。也不起作用:保留 Text Binding 并覆盖DataItemsToString()方法。查看工作,测量没有。

然后我试图使用DataTemplate 或整个页面上的 或 之类的方法强制重新计算,但没有成功InvalidateMeasure()UpdateLayout()

你能解释一下吗?

更新有趣:出于调试原因,
我已将一个简单的自定义附加到 TextBlock 的绑定中。ValueConverter当一个string对象被绑定时,我可以看到它Measure(...)正在触发绑定 - 它首先被解决(我可以看到调试器进入 ValueConverter)然后测量。但是,当如上所述绑定自定义类时,Measure(...)不会触及绑定,我会“稍后”进入ValueConverters 断点。(必须找出确切的时间)

这对您有任何帮助吗?

4

3 回答 3

0

答案很简单..你不是在“银光方式”工作

在 Silverligth 中 - 字符串是否适合屏幕宽度并不重要,如果字符串不适合,只需设置TextBlock.WrapWrap...

由于“旧的思维方式”,您对此有疑问...

但如果你非常想要它,试试这个:

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;
于 2011-03-11T12:27:16.983 回答
0

这是来自http://silverpdf.codeplex.com/的代码

也许它会帮助你,但你必须修改它,使其可用。

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;
}
于 2011-03-11T15:03:40.723 回答
0

解决了

问题是页面控件首先创建和计算,并在生成后添加到显示控件,因为我想避免频繁的 UI 更新。Ai_boy甚至提出了类似的建议,他试图通过使用独立的GridControl 来解决问题 - 不幸的是,这被证明是一种误导性的方法。只有在生成的页面控件被添加到可视化树后,它才会自动解析绑定,从而产生适当的尺寸测量。

希望这对任何人都有帮助。

于 2011-03-15T11:54:03.847 回答