我有一个带有标签控件和页数的窗口 - 标签项。每个选项卡项具有相同的网格布局 - 6行和4列。现在,每个选项卡项都包含具有行和列定义的网格,因此几乎一半的XAML是网格的定义。
如何在一个地方定义此网格并在我的应用程序中重用该定义?模板?用户控制?
除了6x4之外,我还有两个重复的网格尺寸:8x4和6x6。
修改
忘记提及:网格中的控件对于每个选项卡都是不同的。我只想在某些资源中定义一次网格,以便我可以在不同的标签页上重复使用它们。现在XAML看起来像这样:
<TabControl>
<TabItem Header="Property">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- some controls here -->
</Grid>
</TabItem>
<TabItem Header="Style">
<Grid >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- some controls here -->
</Grid>
</TabItem>
... and this repeats for several more tab items
</TabControl>
对表单上的每个标签项重复此网格定义。令我很恼火的是,XAML的一半是网格定义。
有没有办法在一个地方定义这个网格然后重用那个定义?
答案 0 :(得分:30)
我认为最好的方法是将ItemsControl
与ItemsPanelTemplate
一起使用,因为您需要一个容器来存放多个项目:
<FrameworkElement.Resources>
<Style x:Key="GridItemsStyle"
TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</FrameworkElement.Resources>
<TabControl>
<TabItem>
<ItemsControl Style="{StaticResource GridItemsStyle}">
<TextBlock Grid.Row="1" Text="R1" />
<TextBlock Grid.Column="1"
Text="C1" />
</ItemsControl>
</TabItem>
<TabItem>
<ItemsControl Style="{StaticResource GridItemsStyle}">
<TextBlock Grid.Row="2"
Text="R2" />
<TextBlock Grid.Column="2"
Text="C2" />
</ItemsControl>
</TabItem>
</TabControl>
答案 1 :(得分:3)
或者你可以继承Grid ...
using System.Windows.Controls;
public class AlreadySetupGrid:Grid
{
public AlreadySetupGrid()
{
for (int i = 0; i < 4; i++)
{
ColumnDefinitions.Add(new ColumnDefinition());
}
for (int i = 0; i < 6; i++)
{
RowDefinitions.Add(new RowDefinition());
}
}
}
然后使用它而不是普通的网格。
答案 2 :(得分:1)
我有类似的东西。问题是你怎么不把你的数据放入网格?
当你一遍又一遍地使用相同的布局时,我猜你正在为每个单元格添加类似的东西。
我为每个Tab创建了一个自定义ItemsControl来放入Data,然后为显示网格的ItemsControl创建了一个样式。
<Style x:Key="GridItemsStyle"
TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentPresenter Content="{Binding ElementName=Cell00}" Grid.Row="0" Grid.Column="0" />
<ContentPresenter Content="{Binding ElementName=Cell01}" Grid.Row="0" Grid.Column="1" />
<ContentPresenter Content="{Binding ElementName=Cell10}" Grid.Row="1" Grid.Column="0" />
<!-- ...And so on -->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
并在窗口中
<TabControl>
<TabItem>
<local:tab1 Style="{StaticResource GridItemsStyle}" />
</TabItem>
<TabItem>
<local:tab2 Style="{StaticResource GridItemsStyle}" />
</TabItem>
然后每个CustomControl继承自ItemsControl
<ItemsControl x:Class="your_app.tab1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:your_app">
<ContentControl x:Name="Cell00">
<!-- Some stuff here -->
</ContentControl>
<ContentControl x:Name="Cell01">
<!-- Some stuff here -->
</ContentControl>
<ContentControl x:Name="Cell10">
<!-- Some stuff here -->
</ContentControl>
这与Aelij正在做的非常类似,除了我设置了ContentPresenter并将其绑定到一个名称并将itemsControl放入它自己的东西(你可以混合两种解决方案)。
它仍然有很多代码,但我会说你自己保存所有行和列定义,如果你必须稍微修改它,你也只需要在一个地方更改网格。
答案 3 :(得分:0)
通常会为进入选项卡的数据编写DataTemplate。 DataTemplate将包含Grid。
答案 4 :(得分:0)
如何在一个地方定义此网格并在我的应用程序中重用该定义?模板?用户控制?
如果我是你,我会使用重复的代码创建UserControl
或自定义Control
,然后从当前代码中使用该控件。
另一种方法是使用DataTemplate
或ControlTemplate
。
为ControlTemplate
创建TabItem
也会很有效。
答案 5 :(得分:0)
你可以做到,但需要做一些工作:
1)创建一个集合和附加属性,如下所示:
public class ColumnDefinitions : Collection<ColumnDefinition>
{
public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached(
"Source",
typeof(ColumnDefinitions),
typeof(ColumnDefinitions),
new PropertyMetadata(
default(ColumnDefinitions),
OnColumnDefinitionsChanged));
public static void SetSource(Grid element, ColumnDefinitions value)
{
element.SetValue(SourceProperty, value);
}
[AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
[AttachedPropertyBrowsableForType(typeof(Grid))]
public static ColumnDefinitions GetSource(Grid element)
{
return (ColumnDefinitions)element.GetValue(SourceProperty);
}
private static void OnColumnDefinitionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = (Grid)d;
grid.ColumnDefinitions.Clear();
var columnDefinitions = (ColumnDefinitions)e.NewValue;
if (columnDefinitions == null)
{
return;
}
foreach (var columnDefinition in columnDefinitions)
{
grid.ColumnDefinitions.Add(columnDefinition);
}
}
}
2)然后你可以将它用作资源和网格样式,如下所示:
请注意,必须使用x:Shared="False"
。如果没有相同的定义将添加到导致WPF抛出的许多网格中。
<UserControl.Resources>
<demo:ColumnDefinitions x:Key="SomeColumnDefinitions" x:Shared="False">
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</demo:ColumnDefinitions>
<Style x:Key="SomeGridStyle" TargetType="{x:Type Grid}">
<Setter Property="demo:ColumnDefinitions.Source" Value="{StaticResource SomeColumnDefinitions}"></Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="5"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid Style="{StaticResource SomeGridStyle}">
<Rectangle Grid.Row="0"
Grid.Column="0"
Width="120"
Fill="Blue" />
<Rectangle Grid.Row="0"
Grid.Column="1"
Fill="Yellow" />
</Grid>
<Grid Grid.Row="2" demo:ColumnDefinitions.Source="{StaticResource SomeColumnDefinitions}">
<Rectangle Grid.Row="0"
Grid.Column="0"
Width="120"
Fill="Blue" />
<Rectangle Grid.Row="0"
Grid.Column="1"
Fill="Yellow" />
</Grid>
</Grid>