Wpf ItemsControl-栅格子元素自动调整大小
我用Rachel Lim来获取动态行数。我想要实现的是让每一行显示在另一行的下方(完成),能够调整它们的大小(完成-使用GridSplitter),并使内容的大小与屏幕大小成比例 结果: 我想要的是: Xaml:Wpf ItemsControl-栅格子元素自动调整大小,wpf,xaml,blend,Wpf,Xaml,Blend,我用Rachel Lim来获取动态行数。我想要实现的是让每一行显示在另一行的下方(完成),能够调整它们的大小(完成-使用GridSplitter),并使内容的大小与屏幕大小成比例 结果: 我想要的是: Xaml: <Grid> <ItemsControl ItemsSource="{Binding RowSource}" > <ItemsControl.ItemsPanel> <ItemsPanelTe
<Grid>
<ItemsControl ItemsSource="{Binding RowSource}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid local:GridHelper.RowCount="{Binding RowCount}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Grid.Row" Value="{Binding RowNumber}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Col 1" />
<DataGridTextColumn Header="Col 2" />
<DataGridTextColumn Header="Col 3" />
</DataGrid.Columns>
</DataGrid>
<Button Grid.Column="1" Content="Btn" />
</Grid>
<GridSplitter Height="5" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Grid.Row="0" ResizeDirection="Rows" ResizeBehavior="CurrentAndNext"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
internal class MyViewModel
{
public ObservableCollection<RowInfo> RowSource { get; set; }
public int RowCount { get { return RowSource.Count; } }
public MyViewModel()
{
RowSource = new ObservableCollection<RowInfo>()
{
new RowInfo() { RowNumber = 0 },
new RowInfo() { RowNumber = 1 },
new RowInfo() { RowNumber = 2 }
};
}
}
public class RowInfo
{
public int RowNumber { get; internal set; }
}
对您在
GridHelper
类中创建的RowDefinitions
使用星形大小调整:
public static void RowCountChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || (int)e.NewValue < 0)
return;
Grid grid = (Grid)obj;
grid.RowDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.RowDefinitions.Add(
new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); //<--
SetStarRows(grid);
}
我认为你的方法是完全错误的。您不能使用
ItemsControl
,因为GridSplitter
项需要位于ItemsPanel
级别,而不是DataTemplate
-否则,它将无法工作
最好在网格本身上使用自定义行为-请参见下面的示例代码:
public class GridAutoRowChildBehavior : Behavior<Grid>
{
public static readonly DependencyProperty ItemTemplateProperty =
DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(GridAutoRowChildBehavior),
new PropertyMetadata(null, OnGridPropertyChanged));
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(object), typeof(GridAutoRowChildBehavior),
new PropertyMetadata(null, OnGridPropertyChanged));
private static void OnGridPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((GridAutoRowChildBehavior) d).ResetGrid();
}
private void ResetGrid()
{
var source = ItemsSource as IEnumerable;
if (source == null || ItemTemplate == null)
return;
AssociatedObject.Children.Clear();
AssociatedObject.RowDefinitions.Clear();
var count = 0;
foreach (var item in source)
{
var content = new ContentPresenter
{
ContentTemplate = ItemTemplate,
Content = item
};
var splitter = new GridSplitter
{
Height = 5,
VerticalAlignment = VerticalAlignment.Bottom,
HorizontalAlignment = HorizontalAlignment.Stretch
};
AssociatedObject.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
Grid.SetRow(content,count);
Grid.SetRow(splitter,count);
AssociatedObject.Children.Add(content);
AssociatedObject.Children.Add(splitter);
count++;
}
}
public DataTemplate ItemTemplate
{
get { return (DataTemplate) GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
public object ItemsSource
{
get { return GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
}
公共类GridAutoRowChildBehavior:Behavior
{
公共静态只读DependencyProperty ItemTemplateProperty=
DependencyProperty.Register(“ItemTemplate”、typeof(DataTemplate)、typeof(GridAutoRowChildBehavior),
新的PropertyMetadata(null,OnGridPropertyChanged));
公共静态只读依赖项Property ItemsSourceProperty=
DependencyProperty.Register(“ItemsSource”、typeof(object)、typeof(GridAutoRowChildBehavior),
新的PropertyMetadata(null,OnGridPropertyChanged));
私有静态void OnGridPropertyChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
((GridAutoRowChildBehavior)d).ResetGrid();
}
私有void ResetGrid()
{
var source=ItemsSource作为IEnumerable;
if(source==null | | ItemTemplate==null)
返回;
AssociatedObject.Children.Clear();
AssociatedObject.RowDefinitions.Clear();
var计数=0;
foreach(源中的var项)
{
var content=newcontentpresenter
{
ContentTemplate=ItemTemplate,
内容=项目
};
var splitter=新的GridSplitter
{
高度=5,
垂直对齐=垂直对齐。底部,
水平对齐=水平对齐。拉伸
};
AssociatedObject.RowDefinitions.Add(新行定义{Height=new GridLength(1,GridUnitType.Star)});
Grid.SetRow(内容、计数);
Grid.SetRow(拆分器,计数);
AssociatedObject.Children.Add(内容);
AssociatedObject.Children.Add(拆分器);
计数++;
}
}
公共数据模板ItemTemplate
{
获取{return(DataTemplate)GetValue(ItemTemplateProperty);}
set{SetValue(ItemTemplateProperty,value);}
}
公共对象项资源
{
获取{返回GetValue(ItemsSourceProperty);}
set{SetValue(ItemsSourceProperty,value);}
}
}
然后在XAML中编写如下代码:
<Grid>
<i:Interaction.Behaviors>
<local:GridAutoRowChildBehavior ItemsSource="{Binding RowsSource}">
<local:GridAutoRowChildBehavior.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Col 1" />
<DataGridTextColumn Header="Col 2" />
<DataGridTextColumn Header="Col 3" />
</DataGrid.Columns>
</DataGrid>
<Button Grid.Column="1" Content="Btn" />
</Grid>
</DataTemplate>
</local:GridAutoRowChildBehavior.ItemTemplate>
</local:GridAutoRowChildBehavior>
</i:Interaction.Behaviors>
</Grid>
我已经测试了这个,它的工作原理完全符合你的需要
您还需要做的唯一一件事是将Nuget软件包添加到您的项目中,该软件包可以使内容按比例调整大小,但调整大小不正确。调整大小是什么意思?我想使用GridSplitter调整行的大小。我希望内容分布在整个视图中,当我调整窗口大小时,您也希望缩放行和列。我还想使用GridSplitter分别调整每一行的大小。我不确定我是否能很好地回答这个问题,你想要的是,默认情况下,即使行中没有内容,它们也应该有一定的高度。这就是需要的吗?是的,我希望行的大小与窗口大小成比例@mm8做对了这一部分,但是调整大小(使用GridSplitter)停止了,以便正常工作。哦,基本上,您希望内容分布在整个视图中,当我调整窗口大小时,您也希望缩放行和列?完全正确。但我还想使用GridSplitter分别调整每一行的大小。我会试着写一个控件。做得好,迪安!我在哪里可以深入阅读更多关于互动库的内容?这是一个很好的起点,对于可能阅读此内容的人来说只是一个小小的更新:如果您在ItemControl中有行为(与我一样,但在本示例中未显示),则必须覆盖OnAttached并在其中调用ResetGrid。受保护的重写void OnAttached(){base.OnAttached();ResetGrid();}还检查ResetGrid方法中的AssociatedObject是否为null。
<Grid>
<i:Interaction.Behaviors>
<local:GridAutoRowChildBehavior ItemsSource="{Binding RowsSource}">
<local:GridAutoRowChildBehavior.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Col 1" />
<DataGridTextColumn Header="Col 2" />
<DataGridTextColumn Header="Col 3" />
</DataGrid.Columns>
</DataGrid>
<Button Grid.Column="1" Content="Btn" />
</Grid>
</DataTemplate>
</local:GridAutoRowChildBehavior.ItemTemplate>
</local:GridAutoRowChildBehavior>
</i:Interaction.Behaviors>
</Grid>