当CustomControl DataGrid(WPF Datagrid)中的AutoGenerateColumns = false时,DataGrid.Columns中提到的列将不可见

时间:2018-09-19 07:25:11

标签: c# wpf datagrid

我试图通过在WPF中扩展DataGrid来创建自定义控件,但是问题是,当我在视图中使用此自定义控件并通过将AutoGenerateColumns设置为False提供特定列时,不会生成这些列。在OnApplyTemplate()中,当我尝试通过模板获取Datagrid时,其列数显示为0,而在后面的代码视图中,它正确显示了xaml中指定的列数。 我哪里做错了,或者需要为此设置一些额外的东西?

我的自定义控制代码-

public class DataGridControl: DataGrid
 {
    static DataGridControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridControl), new FrameworkPropertyMetadata(typeof(DataGridControl)));
    }

   public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        DataGrid dataGrid = Template.FindName("PART_DataGrid", this) as DataGrid;
        int noOfColumns = dataGrid.Columns.Count// (0 it should come as 3)
    }

}

Generic.xaml(位于控制模板和边框内)

 <ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
.....
xmlns:local="clr-namespace:Siemens.WPF.DataGridControl">
<LinearGradientBrush x:Key="lightBrushBack" EndPoint="0.5,1" StartPoint="0.5,0">
    .....
</LinearGradientBrush>

<LinearGradientBrush x:Key="normalBrushBack" EndPoint="0.5,1" StartPoint="0.5,0">
   ......
</LinearGradientBrush>

<Style TargetType="{x:Type local:DataGridControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:DataGridControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid>
                        <DataGrid x:Name="PART_DataGrid"

                                  ItemsSource="{TemplateBinding ItemsSource}"
                                   AutoGenerateColumns="{TemplateBinding AutoGenerateColumns}">
                            <DataGrid.Resources>

                                <!--A custom DataGridColumnHeadersPresenter is required to "not" display the custom ColumnHeader template as background of the datagrid header-->
                                <Style TargetType="{x:Type DataGridColumnHeadersPresenter}">
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
                                                <Grid>
                                                    <!--"part_fillercolumnheader" (DataGridColumnHeader type) is removed, and a plain rectangle is placed in its place.-->
                                                    <Rectangle  Fill="{StaticResource normalBrushBack}" />
                                                    <!--Leave the item presenter in its place.-->
                                                    <ItemsPresenter x:Name="itemsPresenter" />
                                                </Grid>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                                <!--End of custom DataGridColumnHeadersPresenter template-->

                                <!--Custom Column Header Gripper styling-->
                                <Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
                                    <Setter Property="Width" Value="3"/>
                                    <Setter Property="Foreground" Value="Transparent" />
                                    <Setter Property="Cursor" Value="SizeWE"/>
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="{x:Type Thumb}">
                                                <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Foreground}"/>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>

                                <!--Custom Column Header template to show extra elements in the header-->
                                <Style TargetType="{x:Type DataGridColumnHeader}">
                                    <Setter Property="FontWeight" Value="Bold" />
                                    <Setter Property="HorizontalContentAlignment" Value="Center" />
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">

                                                <!--Let's keep the top section grid to contain the DataGridHeaderBorder, and left+right thumbs.-->
                                                <Grid x:Name="fullHeader" Background="{StaticResource normalBrushBack}">

                                                    <!--Here is the theme based DataGridHeaderBorder. I've used Aero here.-->
                                                    <aero:DataGridHeaderBorder x:Name='HeaderBorder'
                                                           SortDirection="{TemplateBinding SortDirection}"
                                                           IsHovered="{TemplateBinding IsMouseOver}"
                                                           IsPressed="{TemplateBinding IsPressed}"
                                                           IsClickable="{TemplateBinding CanUserSort}"
                                                           BorderThickness="0,0,1,1"
                                                           BorderBrush="{TemplateBinding Foreground}"
                                                           Background="Transparent"
                                                           SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
                                                           SeparatorBrush="#FFC9CACA">

                                                        <!--Put 3 elements inside the border: Content of header, a drop down button, and a sort order indicator.-->
                                                        <Grid Margin="0,0,0,0">
                                                            <Grid.RowDefinitions>
                                                                <RowDefinition MinHeight="15" Height="20" />
                                                            </Grid.RowDefinitions>
                                                            <Grid.ColumnDefinitions>
                                                                <!--For ContentPresenter-->
                                                                <ColumnDefinition Width="*" />
                                                                <!--For drop down button-->
                                                                <ColumnDefinition Width="23" />
                                                                <!--For sort order indicator-->
                                                                <ColumnDefinition Width="12" />
                                                            </Grid.ColumnDefinitions>

                                                            <!--A hidden rectangle is placed to be shown when mouse hovers on the column (to highlight the column.)-->
                                                            <Rectangle x:Name="HoverRectangle"
                                                                    Stretch="Fill"
                                                                    Grid.ColumnSpan="3"
                                                                    Fill="{StaticResource lightBrushBack}"
                                                                    Opacity="0"
                                                                    StrokeThickness="0" />

                                                            <!--Content of the header.-->
                                                            <ContentPresenter Grid.Column="0" 
                                                                              Grid.Row="0"
                                                                              Margin="2,0,0,0"
                                                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                                  VerticalAlignment="{TemplateBinding VerticalAlignment}"
                                                                  HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                                                                  Cursor="{TemplateBinding Cursor}" />

                                                            <!--A drop down filter button.-->
                                                            <Button x:Name="PART_FilterBtn" 
                                                                    HorizontalAlignment="Right"
                                                                    Command="{Binding FilterClickCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}"
                                                                    CommandParameter="{Binding ElementName=HeaderBorder}"
                                                                    Grid.Row="0" Cursor="Hand"
                                                                    Grid.Column="1">
                                                                <Button.Template>
                                                                    <ControlTemplate>
                                                                        <Path Data="M 0,0 L 1,1 1,3 2,3 2,1 3,0 Z"
                                                                              Stretch="UniformToFill"
                                                                              Stroke="{TemplateBinding Foreground}"
                                                                              Fill="{TemplateBinding Foreground}"
                                                                              Margin="4,4,0,4"/>
                                                                    </ControlTemplate>
                                                                </Button.Template>
                                                            </Button>

                                                            <Path x:Name="PART_SortArrow"
                                                                  Grid.Column="2"
                                                                  HorizontalAlignment="Center" VerticalAlignment="Center" 
                                                                  Width="8"
                                                                  RenderTransformOrigin=".5,.5"
                                                                  Visibility="Visible"
                                                                  Fill="{TemplateBinding Foreground}"
                                                                  Stretch="Uniform"
                                                                  Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z">
                                                            </Path>

                                                        </Grid>
                                                    </aero:DataGridHeaderBorder>

                                                    <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}" />
                                                    <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}" />
                                                </Grid>

                                                <ControlTemplate.Triggers>

                                                    <Trigger Property="SortDirection" Value="Descending">
                                                        <Setter TargetName="PART_SortArrow" Property="RenderTransform">
                                                            <Setter.Value>
                                                                <RotateTransform Angle="180" />
                                                            </Setter.Value>
                                                        </Setter>
                                                    </Trigger>

                                                    <Trigger Property='IsMouseOver' SourceName="fullHeader" Value='True'>
                                                        <Trigger.EnterActions>
                                                            <BeginStoryboard>
                                                                <Storyboard>
                                                                    <DoubleAnimation BeginTime="00:00:00" Duration="00:00:00.20000"
                                                                 Storyboard.TargetName="HoverRectangle"
                                                                 Storyboard.TargetProperty="(UIElement.Opacity)"
                                                                 To='1.0' />
                                                                </Storyboard>
                                                            </BeginStoryboard>
                                                        </Trigger.EnterActions>
                                                        <Trigger.ExitActions>
                                                            <BeginStoryboard>
                                                                <Storyboard>
                                                                    <DoubleAnimation BeginTime="00:00:00" Duration="00:00:00.20000"
                                                                 Storyboard.TargetName="HoverRectangle"
                                                                 Storyboard.TargetProperty="(UIElement.Opacity)"
                                                                 To='0' />
                                                                </Storyboard>
                                                            </BeginStoryboard>
                                                        </Trigger.ExitActions>
                                                    </Trigger>
                                                </ControlTemplate.Triggers>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
                                            <Setter Property="Background">
                                                <Setter.Value>
                                                    <LinearGradientBrush options:Freeze="True" StartPoint="0.504,0.03" EndPoint="0.504,1.5">
                                                        <GradientStop Offset="0.0" Color="#E3F7FF" />
                                                        <GradientStop Offset="0.3" Color="#E3F7FF" />
                                                        <GradientStop Offset="0.35" Color="#BCECFE" />
                                                        <GradientStop Offset="1.0" Color="#B9E9FC" />
                                                    </LinearGradientBrush>
                                                </Setter.Value>
                                            </Setter>
                                            <Setter Property="BorderBrush" Value="#69BBE3" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                                <!--End of custom DataGridColumnHeader template-->

                            </DataGrid.Resources>
                        </DataGrid>
                        <Popup x:Name="PART_PopUp" 
                                Grid.Column="3"
                                AllowsTransparency="True" 
                                AllowDrop="True" 
                                Width="200"
                                Height="253"
                                MinHeight="253"
                                MaxHeight="253"
                                PopupAnimation="Slide"
                                VerticalOffset="-15"
                                IsOpen="{Binding IsFilterPopUpVisible,RelativeSource={RelativeSource AncestorType=local:DataGridControl}}"
                                PlacementTarget="{Binding ElementName=PART_FilterBtn}"
                                StaysOpen="False"
                                Placement="Mouse" >
                            <Border Background="White" BorderBrush="DarkGray" BorderThickness="2">
                                <StackPanel Orientation="Vertical">
                                    <StackPanel Orientation="Horizontal" Margin="10,5,0,5">
                                        <Button Margin="10,0,0,0" Name="PART_SelectAllBtn" Command="{Binding SelectAllClickCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}" CommandParameter="{Binding ElementName=PART_ListBox}" >
                                            <Button.Template>
                                                <ControlTemplate>
                                                    <TextBlock Text="Select All" Foreground="Blue" Cursor="Hand" />
                                                </ControlTemplate>
                                            </Button.Template>
                                        </Button>
                                        <Button Margin="30,0,0,0" Name="PART_SelectNoneBtn" Command="{Binding SelectNoneClickCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}" CommandParameter="{Binding ElementName=PART_ListBox}" >
                                            <Button.Template>
                                                <ControlTemplate>
                                                    <TextBlock Text="Select None" Foreground="Blue" Cursor="Hand" />
                                                </ControlTemplate>
                                            </Button.Template>
                                        </Button>
                                    </StackPanel>
                                    <TextBox x:Name="PART_TextBox" Width="185" Height="25" Text="" Margin="3,0,3,3"/>
                                    <ListBox x:Name="PART_ListBox" 
                                             Height="160" 
                                             MaxHeight="160" 
                                             MinHeight="160" 
                                             Width="185" 
                                             SelectionMode="Multiple" 
                                             DisplayMemberPath="Value"
                                             HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                                             HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                             VerticalAlignment="{TemplateBinding VerticalAlignment}"
                                             VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                             ItemsSource="{Binding FilterCollectionList, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}" Margin="0,0,0,5" 
                                             ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible">
                                        <ListBox.ItemContainerStyle>
                                            <Style TargetType="{x:Type ListBoxItem}">
                                                <Setter Property="OverridesDefaultStyle" Value="true" />
                                                <Setter Property="SnapsToDevicePixels" Value="true" />
                                                <Setter Property="HorizontalContentAlignment" Value="Left"/>
                                                <Setter Property="VerticalContentAlignment" Value="Center"/>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="ListBoxItem" >
                                                            <CheckBox x:Name="PART_CheckBox" Margin="5,2" IsChecked="{Binding IsSelected}">
                                                                <i:Interaction.Triggers>
                                                                    <i:EventTrigger EventName="Checked">
                                                                        <i:InvokeCommandAction Command="{Binding CheckedCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}"/>
                                                                    </i:EventTrigger>
                                                                    <i:EventTrigger EventName="Unchecked">
                                                                        <i:InvokeCommandAction Command="{Binding CheckedCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}"/>
                                                                    </i:EventTrigger>
                                                                </i:Interaction.Triggers>
                                                                <ContentPresenter />
                                                            </CheckBox>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </ListBox.ItemContainerStyle>
                                    </ListBox>
                                    <StackPanel Orientation="Horizontal" Margin="0,0,0,15" HorizontalAlignment="Center">
                                        <Button x:Name="PART_OkBtn" Height="22" Width="70" Content="Ok" 
                                                                                    IsEnabled="{Binding IsOkButtonEnabled, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}"
                                                                                    Command="{Binding OkButtonClickCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}"
                                                                                     />
                                        <Button x:Name="PART_CancelBtn" Height="22" Width="70" Content="Cancel" Margin="5,0,0,0" 
                                                                                    Command="{Binding CancelButtonClickCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridControl}}}" 
                                                                                    />
                                    </StackPanel>
                                </StackPanel>
                            </Border>
                        </Popup>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

MainWindow.xaml

 <dataGrid:DataGridControl x:Name="dataGridControl" AutoGenerateColumns="False">
        <dataGrid:DataGridControl.Columns>
            <DataGridTextColumn Header="RollNo" Binding="{Binding RollNo}" />
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
            <DataGridTextColumn Header="FirstName" Binding="{Binding FirstName}" />
        </dataGrid:DataGridControl.Columns>
    </dataGrid:DataGridControl>

MainWindow.xaml.cs

public MainWindow()
    {
        InitializeComponent();
        List<Student> studList =
        new List<Student>() {  new Student {  RollNo = 1, Name = "Full Name 
        1", FirstName = "FirstName1", LastName="LastName1", Address = 
        "Pune1", PinCode= "411057"},};

        dataGridControl.ItemsSource = studList; 
         int noOfColumns = dataGridControl.Columns.Count; //(showing 3 as expected)
    }

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:0)

创建用于自定义控件的属性

 #region GridColumns

 private ObservableCollection<DataGridColumn> _gridColumns;
 public ObservableCollection<DataGridColumn> GridColumns
 {
     get => _gridColumns;
 }

 #endregion GridColumns

使用方法OnApplyTemplate从创建的属性中添加列

 public override void OnApplyTemplate()
 {
     base.OnApplyTemplate();

     if (!AutoGenerateColumns)
     {
         var grid = GetTemplateChild("PART_Grid") as DataGrid;
         foreach (var column in _gridColumns)
             grid.Columns.Add(column);
     }
 }

更改MainWindow.xaml

<dataGrid:DataGridControl x:Name="dataGridControl" AutoGenerateColumns="False">
    <dataGrid:DataGridControl.GridColumns>
        <DataGridTextColumn Header="RollNo" Binding="{Binding RollNo}" />
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
        <DataGridTextColumn Header="FirstName" Binding="{Binding FirstName}" />
    </dataGrid:DataGridControl.GridColumns>
</dataGrid:DataGridControl>