spr*_*y76 7 c# wpf performance xaml .net-4.0
如果您运行下面的示例窗口,则上面的ItemsControl将更新布局几秒钟,直到最后所有列都具有正确的宽度(正确=与较低ItemsControl中的列相同).
您可以更改窗口的宽度并水平和垂直滚动ScrollViewer周围的较低ItemsControls - 但只要更改窗口的高度,布局就会翻转几秒钟.
注意:没有像网格无限更新大小的其他问题那样的大小调整歧义.
是我做错了什么 - 如果是的话,我怎么能解决这个问题? - 或者我应该将此问题发布到Microsoft-Connect?
代码背后:
namespace DynamicGridColumnBinding
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
public partial class MainWindow
{
private static readonly CultureInfo[] cultureInfos =
CultureInfo.GetCultures(CultureTypes.NeutralCultures).Take(15).ToArray();
public MainWindow()
{
this.InitializeComponent();
}
public static IEnumerable<CultureInfo> AllCultures
{
get { return cultureInfos; }
}
private void GridInitialized(object sender, EventArgs e)
{
var grid = (Grid)sender;
for ( int i = 0; i < cultureInfos.Length; i++ )
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = GridLength.Auto,
SharedSizeGroup = "g" + i,
});
}
private void ScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
{
if ( e.HorizontalChange != 0 )
this.legendScroller.ScrollToHorizontalOffset(e.HorizontalOffset);
}
}
}
Run Code Online (Sandbox Code Playgroud)
XAML:
<FrameworkElement.Resources>
<ItemsPanelTemplate x:Key="panelTemplate">
<Grid Initialized="GridInitialized" />
</ItemsPanelTemplate>
<Style TargetType="ContentPresenter" x:Key="containerStyle">
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource Self}, Path=(ItemsControl.AlternationIndex)}" />
<Setter Property="Grid.Column" Value="{Binding RelativeSource={RelativeSource Self}, Path=(ItemsControl.AlternationIndex)}" />
</Style>
<Style TargetType="TextBlock" x:Key="textStyle">
<Setter Property="Padding" Value="5" />
<Setter Property="Background" Value="Lime" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</FrameworkElement.Resources>
<DockPanel Grid.IsSharedSizeScope="True" DataContext="{Binding Source={x:Static local:MainWindow.AllCultures}}">
<ScrollViewer DockPanel.Dock="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled"
x:Name="legendScroller">
<ItemsControl ItemsSource="{Binding}" AlternationCount="{x:Static System:Int32.MaxValue}" Margin="0 0 500 0"
ItemsPanel="{StaticResource panelTemplate}" ItemContainerStyle="{StaticResource containerStyle}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type glob:CultureInfo}">
<GroupBox Header="{Binding Name}" HeaderStringFormat="[ {0} ]">
<TextBlock Style="{StaticResource textStyle}"
Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}" />
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<TextBlock Foreground="Red" DockPanel.Dock="Top" Margin="0 10" FontSize="20" Text="some random arbitrary content in between" />
<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto" ScrollChanged="ScrollViewerScrollChanged">
<ItemsControl ItemsSource="{Binding}" AlternationCount="{x:Static System:Int32.MaxValue}"
ItemsPanel="{StaticResource panelTemplate}" ItemContainerStyle="{StaticResource containerStyle}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type glob:CultureInfo}">
<Border Background="DodgerBlue" Padding="5" Margin="1">
<GroupBox Header="{Binding DisplayName}">
<TextBlock Style="{StaticResource textStyle}" Padding="5 100"
Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}" />
</GroupBox>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
Run Code Online (Sandbox Code Playgroud)
顺便说一句:如果你强制上部ItemsControl的项目是大小给予(通过添加MinWidth="200"
到GroupBox),那么较低的ItemsControl将改为愚蠢.
BTW2:从大约开始 8个共享大小的列(在样本中有15个,受控制.Take(15)
)你会看到重新排列显示,并且它会在你添加的每一列中及时翻倍 - 所以20列几乎不会在几分钟内结束.
BTW3:3个月内没有收到任何评论是非常令人沮丧的.
有趣的是,我三个月前就 +1 了这个问题,但没有回答。您没有收到回复的原因可能是因为它很困难!
我现在仍然没有太多要说的,除了 WPF 布局分两次执行 - 测量和排列 - 并且元素的后续大小调整可能会触发其他元素上的布局等......
为了正确调整列的大小,WPF 正在执行以下操作:
... ETC
为我的简单化观点道歉。您有多少列(因此共享大小组的数量)?另一个问题。您运行什么操作系统和 .NET Framework?例如,我听说 WindowsXP 上的 WPF 中的 SharedSizeGroup 数量有限制。不确定它是否在以后的操作系统中得到修复。
作为解决方法,您可以自己实现此行为吗?这意味着您可以创建自己的附加属性来测量网格中的每个元素(所有列、所有行),然后设置每列的大小一次吗?与逐列的基础相反。
问候,