2010-05-21 31 views
19

Tôi có cửa sổ có điều khiển tab và số trang - mục tab. Mỗi mục tab có bố cục lưới giống nhau - 6 hàng và 4 cột. Bây giờ, mỗi mục tab chứa lưới với định nghĩa hàng và cột, vì vậy gần một nửa XAML là định nghĩa của lưới.Cách tạo bố cục lưới WPF có thể tái sử dụng

Làm cách nào để xác định lưới này ở một nơi và sử dụng lại định nghĩa đó trong ứng dụng của tôi? Bản mẫu? Kiểm soát người dùng?

Bên cạnh 6x4, tôi chỉ có hai thứ nguyên lưới khác lặp lại: 8x4 và 6x6.

Chỉnh sửa:
Quên đề cập: các điều khiển trong lưới khác nhau cho mỗi tab. Tôi chỉ muốn có lưới được xác định một lần trong một số tài nguyên để tôi có thể tái sử dụng chúng trên các trang tab khác nhau. Bây giờ XAML trông giống như sau:

<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> 

Định nghĩa lưới này lặp lại cho từng mục tab trên biểu mẫu. Nó làm phiền tôi rằng một nửa XAML là định nghĩa lưới.

Có cách nào để xác định lưới này tại một nơi và sau đó sử dụng lại định nghĩa đó không?

Trả lời

0

Thông thường, một người sẽ viết DataTemplate cho dữ liệu đi vào tab. DataTemplate đó sẽ chứa Grid.

0

Làm cách nào để xác định lưới này ở một nơi và sử dụng lại định nghĩa đó trong ứng dụng của tôi? Bản mẫu? Kiểm soát người dùng?

Nếu tôi là bạn, tôi sẽ tạo một UserControl hoặc tùy chỉnh Control bằng mã lặp lại, sau đó chỉ sử dụng điều khiển đó từ mã hiện tại.

Một cách tiếp cận khác là sử dụng DataTemplate hoặc ControlTemplate.

Tạo một ControlTemplate cho số TabItem cũng sẽ hoạt động tốt.

25

Cách tốt nhất theo ý kiến ​​của tôi sẽ được sử dụng ItemsControl với một ItemsPanelTemplate, vì bạn cần một container cho nhiều mục:

<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> 
+0

Hoạt động đơn giản như giao diện –

+0

Câu trả lời hay! Đây chỉ là những gì tôi đang tìm kiếm, cảm ơn nhiều vì đã chia sẻ :-) –

1

Tôi có một cái gì đó tương tự. câu hỏi là làm thế nào để bạn wan't để đưa dữ liệu của bạn vào lưới?

Khi bạn sử dụng cùng một bố cục lặp đi lặp lại, tôi đoán bạn đang đặt những thứ tương tự cho mỗi ô.

Tôi đã tạo một ItemsControl tùy chỉnh cho mỗi Tab để đưa Dữ liệu vào và sau đó tạo một kiểu cho ItemsControl hiển thị lưới.

<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> 

và trong cửa sổ

<TabControl> 
<TabItem> 
    <local:tab1 Style="{StaticResource GridItemsStyle}" /> 
</TabItem> 
<TabItem> 
    <local:tab2 Style="{StaticResource GridItemsStyle}" /> 
</TabItem> 

sau đó mỗi CustomControl kế thừa từ 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> 

này là rất tương tự với những gì Aelij đang làm ngoại trừ tôi đặt ContentPresenter và ràng buộc nó vào một tên và đặt itemsControl trong điều riêng của nó (bạn có thể trộn b oth giải pháp).

Nó vẫn còn rất nhiều mã nhưng tôi sẽ nói bạn tiết kiệm cho mình tất cả các định nghĩa hàng và cột tất cả các thời gian và bạn cũng chỉ phải thay đổi lưới ở một nơi nếu bạn phải sửa đổi nó một chút.

3

Hoặc bạn chỉ có thể kế thừa từ Lưới ...

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()); 
     } 
    } 
} 

Và sau đó sử dụng thay vì Lưới bình thường của bạn.

+0

điều này nghe giống như một kế hoạch tốt hơn nhưng điều này là tôi không nhận được colums và hàng trong thời gian thiết kế. tức là bất kỳ yếu tố nào được xác định trong lưới sẽ không được định vị chính xác – Gurpreet

0

Bạn có thể làm điều đó nhưng nó đòi hỏi một số công việc:

1) Tạo một bộ sưu tập và tài sản gắn liền như thế này:

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) Sau đó, bạn có thể sử dụng nó như là một nguồn tài nguyên và trong một phong cách cho lưới như thế này: Lưu ý rằng x:Shared="False" phải được sử dụng. Nếu không cùng định nghĩa sẽ được thêm vào nhiều lưới khiến WPF bị ném.

<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> 
Các vấn đề liên quan