更改WPF中窗口控件模板的内容

时间:2014-03-15 07:22:27

标签: wpf controltemplate

我有一个带有多个窗口的应用程序(作为对话框),大多数窗口都有相同的控件(左边是扩展器,右边是数据网格)。

开发此类应用程序的最佳方法是什么?我想为这个窗口编写一个控件模板:

<ControlTemplate x:Key="WindowControlTemplate" TargetType="{x:Type Window}">
    <Border Background="{TemplateBinding Background}" 
            BorderBrush="{TemplateBinding BorderBrush}" 
            BorderThickness="{TemplateBinding BorderThickness}" >
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.20*"/>
                <ColumnDefinition Width="0.80*"/>
            </Grid.ColumnDefinitions>

            <Expander ExpandDirection="Right" IsExpanded="True" Grid.Column="0">
                <Expander.Header>
                    <TextBlock FontSize="14" Text="Control Panel" Background="Gray">
                        <TextBlock.LayoutTransform>
                            <RotateTransform Angle="90"/>
                        </TextBlock.LayoutTransform>
                    </TextBlock>
                </Expander.Header>
                <Grid >
                    <Grid.Background>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#FFBFB5B5" Offset="0"/>
                            <GradientStop Color="#FFC97A7A" Offset="1"/>
                        </LinearGradientBrush>
                    </Grid.Background>
                </Grid>
            </Expander>

            <DataGrid Grid.Column="2">
            </DataGrid>

        </Grid>
    </Border>

</ControlTemplate>

然后我使用此模板定义了一个新窗口,但我不知道如何向扩展器添加控件以及如何将数据绑定到数据网格。

1 个答案:

答案 0 :(得分:0)

如果我这样说的话,这很简单:

  1. 您不需要多个窗口或多个控件来实现此目的。
  2. 只需创建一个包含所有必需部分的窗口。
  3. DataTemplate写在每个部分的Resources内。
  4. 如果您按照以下说明执行此操作,则View的不同部分可以找到正确的模板。
  5. 在此方法中,将根据DataContext的正确类型自动选择和设置在Expander或ContentPresenter的Resources中使用的DataTemplates。请注意,我必须从这些DataTemplates和Style中消除x:Key,用于设置datagrids的公共属性。

    <Grid>
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="0.20*"/>
             <ColumnDefinition Width="0.80*"/>
         </Grid.ColumnDefinitions>
    
         <Expander ExpandDirection="Right" IsExpanded="True" Grid.Column="0">
             <Expander.Resources>
                 <DataTemplate DataType="{x:Type vm:MyType1}">
                    <Grid>
                        <Grid.Background>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FFBFB5B5" Offset="0"/>
                                <GradientStop Color="#FFC97A7A" Offset="1"/>
                            </LinearGradientBrush>
                        </Grid.Background>
                    </Grid>
                 </DataTemplate>
                 <DataTemplate DataType="{x:Type vm:MyType2}">
                     <Grid>
                         <Grid.Background>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FAAA" Offset="0"/>
                                <GradientStop Color="#F0F0" Offset="1"/>
                            </LinearGradientBrush>
                         </Grid.Background>
                     </Grid>
                 </DataTemplate>
             </Expander.Resources>
    
             <Expander.Header> 
                 <TextBlock FontSize="14" Text="Control Panel" Background="Gray">
                      <TextBlock.LayoutTransform>
                          <RotateTransform Angle="90"/>
                      </TextBlock.LayoutTransform>
                 </TextBlock>
             </Expander.Header>
    
             <ContentPresenter Content="{Binding}">
         </Expander>
    
         <ContentPresenter Content="{Binding}">
             <ContentPresenter.Resources>
                 <DataTemplate DataType="{x:Type vm:MyType1}">
                    <DataGrid ItemsSource="{Binding MyList1}">
                       <DataGrid.Columns>
                          <DataGridTextColumn Binding="{Binding MyProperty1}"/>
                       </DataGrid.Columns>
                    </DataGrid>
                 </DataTemplate>
    
                 <DataTemplate DataType="{x:Type vm:MyType2}">
                    <DataGrid ItemsSource="{Binding MyList2}">
                       <DataGrid.Columns>
                          <DataGridTextColumn Binding="{Binding MyProperty2}"/>
                       </DataGrid.Columns>
                    </DataGrid>
                 </DataTemplate>
             </ContentPresenter.Resources>
         </ContentPresenter>
    </Grid>
    

    在这个例子中,我使用了两个名为MyType1的视图模型(有一个名为MyList1的列表,每个元素都是视图模型本身,并且有一个名为MyProperty1的属性)和MyType2(与MyType1相同,但与MyList2和MyProperty2相同)

    您可以打开如下窗口:

    Window w1 = new Window();
    w1.DataContext = new MyType1();
    w1.Show();
    

    注意:

    另外,为了避免DataGrid代码中的冗余,您可以将样式添加到ContentPresenter.Resources而不添加x:Key来设置DataGrid的某些属性。这些属性将应用于DataGrid的任何ContentPresenter

         <ContentPresenter Content="{Binding}">
             <ContentPresenter.Resources>
                <Style TargetType="{x:Type DataGrid}">
                    <Setter Property="AutoGenerateColumns" Value="False"/>
                </Style>
                <DataTemplate DataType="{x:Type vm:MyType1}">
                    <DataGrid ItemsSource="{Binding MyList1}">
                    ...
                 ...
              ...
    

    注意:

    错误的代码:

        <DataGrid ItemsSource="{Binding Items}">
            <DataGrid.Resources>
                <Style TargetType="{x:Type DataGrid}">
                    <Setter Property="DataGrid.Columns">
                        <Setter.Value>
                            <DataGridTextColumn Binding="{Binding}"/>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGrid.Resources>
        </DataGrid>
    

    我没有使用上面的代码来推广DataGrid的原因是DataGrid.Columns是一个附加属性,不能在样式的setter中设置。但是如果所有对话框中的datagrid列都相同,则可以使用更简单的datagrid方法。

    这样你就必须有一个列表及其元素属性的通用名称:

        <DataGrid ItemsSource="{Binding MyCommonList}">
           <DataGrid.Columns>
              <DataGridTextColumn Binding="{Binding MyCommonProperty}"/>
           </DataGrid.Columns>
        </DataGrid>