【问题标题】:Silverlight Measure Method not working properly depending of databound object?Silverlight Measure Method 无法根据数据绑定对象正常工作?
【发布时间】:2011-03-11 12:02:51
【问题描述】:

更新二 问题是solved。谢谢。


对于一个简单的 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 更改为 &lt;TextBlock Text="{Binding Path=Value1}"... 得到的视图是相同的,但是 Measure(...) 方法不会返回预期值,项目的高度始终为零。也不起作用:保留文本绑定并覆盖 DataItems ToString() 方法。查看工作,Measure 没有。

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

你能解释一下吗?

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

这对您有任何帮助吗?

【问题讨论】:

    标签: silverlight silverlight-4.0 printing measure


    【解决方案1】:

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

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

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

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

    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;
    

    【讨论】:

    • 谢谢!不幸的是,它没有用,我什至按照描述暂时从它的父级中删除了controlToMesure。对于每个测试项目,尺寸的高度为 4 - 这是纯边距高度(2 顶部 + 2 底部)。虽然绑定字符串仍然可以正确测量,但我想我可能在数据绑定方面遇到“时间”问题..?
    • 嗯,可能有很多原因......我可以从我个人的经验中说 - 如果你尝试做一些不是“Silverlight 方式”的事情,你最终会遇到很多错误......
    • 并尝试将此更改为Measure(new Size(pageDimensions.Width, Double.PositiveInfinity));Measure(new Size(pageDimensions.Width, pageDimensions.Height));
    • 感谢 Ai_boy,我已经做了描述的更改,发现 Measure 方法的 size 参数不影响结果
    【解决方案2】:

    这是来自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;
    }
    

    【讨论】:

    • 不错的方法,但我需要在这里有 TextBlock 的 Text 值,但我没有,它必须绑定到 DataContext 对象......好吧,你可以说我可以以编程方式添加绑定表达式而不是设置文本 - 正确。但我担心我会遇到同样的效果 - 绑定不会足够早地解决。此外,如果使用更高级的数据模板,这将变得很糟糕 - 该主题仅描述了一个基本阶段。
    【解决方案3】:

    已解决

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-18
      • 2015-09-28
      • 2013-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      相关资源
      最近更新 更多