Silverlight 测量方法无法根据数据绑定对象正常工作?

发布于 2024-10-21 04:06:44 字数 2230 浏览 9 评论 0 原文

更新二 问题已解决。谢谢。


对于一个简单的 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 更改为 时,结果视图是相同的,但是 Measure(...) 方法不会返回预期值,Items 的高度始终为零。同样不起作用:保留文本绑定并覆盖 DataItemToString() 方法。查看有效,而测量无效。

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

你能解释一下吗?

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

这对您有任何帮助吗?

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 TextBlock'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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冰葑 2024-10-28 04:06:44

答案很简单..您不是以“silverlight方式”工作

在Silverligth中 - 字符串是否适合屏幕宽度并不重要,如果字符串不适合,只需设置< code>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;

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;
韬韬不绝 2024-10-28 04:06:44

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

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;
}
友欢 2024-10-28 04:06:44

解决了

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文