WPF Datagrid связывающий заголовки пользовательского столбца

Я пытаюсь выяснить, как связать заголовок столбца DataGrid WPF и основные данные к источнику данных с помощью шаблона MVVM. Результат, который я ищу, был бы похож на это:

alt text
(источник: vallelunga.com)

Я успешно разработал заголовки здесь, но я не уверен, как связать значения в заголовках. А именно, свойство IsChecked флажка, выбранный индекс поля комбинированного списка и значение текстового поля.

Я ранее использовал простой DataTable для заполнения основных данных сетки, но я испытываю необходимость в чем-то более сложном для содержания и данных сетки и значений для каждого столбца. Или возможно я могу сохранить их как отдельные объекты полностью.

Так, у кого-либо есть какая-либо идея того, как я мог бы осуществить эту привязку? Одно ограничение - то, что столбцы должны быть автоматически сгенерированы, так как я понятия не имею, чем они будут до времени выполнения. Приложение просто загружается, данные формируют электронную таблицу Excel и может быть любое число существующих столбцов.

Спасибо, Brian

8
задан Glorfindel 12 June 2019 в 07:04
поделиться

3 ответа

Вот что я в итоге сделал, чтобы использовать это с шаблоном MVVM:

У меня есть два набора данных для привязки к моей модели представления: один для фактические данные сетки и один для заголовков столбцов. В настоящее время они представлены в виде двух свойств:

// INotifyPropertyChanged support not shown for brevity
public DataTable GridData { get; set; } 
public BindingList<ImportColumnInfo> ColumnData { get; set; }

Уловка для работы с двумя разными наборами данных заключается в сетке. Я создал подкласс DataGrid и дал сетке дополнительный источник данных под названием ColumnSource в качестве свойства зависимости. Это то, что привязано к ColumnData в моей модели представления. Затем я устанавливаю заголовок каждого автоматически сгенерированного столбца для соответствующим образом проиндексированных данных в источнике данных ColumnSource. Код выглядит следующим образом:

public class ImporterDataGrid : DataGrid
{
    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
    {
        base.OnAutoGeneratingColumn(e);

        int columnIndex = this.Columns.Count;
        var column = new ImporterDataGridColumn();
        column.Header = ColumnSource[columnIndex];
        column.Binding = new Binding(e.PropertyName) { Mode = BindingMode.OneWay };
        e.Column = column;
    }

    public IList ColumnSource
    {
        get { return (IList)GetValue(ColumnSourceProperty); }
        set { SetValue(ColumnSourceProperty, value); }
    }

    public static readonly DependencyProperty ColumnSourceProperty = DependencyProperty.Register("ColumnSource", typeof(IList), typeof(ImporterDataGrid), new FrameworkPropertyMetadata(null));

}

Теперь я могу выполнить обычную привязку данных в шаблонном заголовке моих столбцов, который будет привязан к данным в свойстве ColumnData моей модели представления.

ОБНОВЛЕНИЕ: меня попросили показать XAML для моей сетки. Это действительно просто, но вот оно:

<Controls:ImporterDataGrid 
    AutoGenerateColumns="True" x:Name="previewDataGrid"
    VerticalScrollBarVisibility="Visible"
    HorizontalScrollBarVisibility="Visible"
    IsReadOnly="True"
    SelectionMode="Extended"
    HeadersVisibility="Column"
    ItemsSource="{Binding PreviewData}"
    ColumnSource="{Binding PreviewColumnData}"
    Style="{StaticResource ImporterDataGridStyle}"
    Background="White" CanUserReorderColumns="False" CanUserResizeRows="False"
    CanUserSortColumns="False" AlternatingRowBackground="#FFFAFAFA" AllowDrop="True" />

А вот ImporterColumnHeaderStyle:

<Style x:Key="ImporterDataGridColumnHeaderStyle" TargetType="{x:Type toolkit:DataGridColumnHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type toolkit:DataGridColumnHeader}">
                <Grid>
                    <toolkit:DataGridHeaderBorder Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsClickable="{TemplateBinding CanUserSort}" IsHovered="False" IsPressed="False" SortDirection="{TemplateBinding SortDirection}">
                        <Grid>
                            <CheckBox Height="16" Margin="6,6,16,0" Name="importCheckBox" IsChecked="{Binding Path=Import}" VerticalAlignment="Top">Import Column</CheckBox>
                            <StackPanel IsEnabled="{Binding Path=Import}">
                                <ComboBox Height="24" Margin="6,29,6,0" Name="columnTypeComboBox" VerticalAlignment="Top" SelectedValue="{Binding ColumnType}" ItemsSource="{Binding Source={local:EnumList {x:Type Models:ImportColumnType}}}">
                                </ComboBox>
                                <TextBox Height="23"  Margin="6,6,6,33" Name="customHeadingTextBox" VerticalAlignment="Bottom" Text="{Binding Path=CustomColumnName}" IsEnabled="{Binding ColumnType, Converter={StaticResource ColumnTypeToBooleanConverter}}" />
                            </StackPanel>
                            <TextBlock Height="20" Margin="6,0,6,7" Name="originalHeadingTextBlock" Text="{Binding Path=OriginalColumnName}" VerticalAlignment="Bottom" Foreground="Gray" />
                        </Grid>
                    </toolkit:DataGridHeaderBorder>

                    <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
                        <Thumb.Style>
                            <Style TargetType="{x:Type Thumb}">
                                <Setter Property="Width" Value="8"/>
                                <Setter Property="Background" Value="Transparent"/>
                                <Setter Property="Cursor" Value="SizeWE"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                            <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Thumb.Style>
                    </Thumb>
                    <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
                        <Thumb.Style>
                            <Style TargetType="{x:Type Thumb}">
                                <Setter Property="Width" Value="8"/>
                                <Setter Property="Background" Value="Transparent"/>
                                <Setter Property="Cursor" Value="SizeWE"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                            <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Thumb.Style>
                    </Thumb>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
8
ответ дан 5 December 2019 в 20:16
поделиться

Я определенно являюсь WPF / MVVM / ноу-база данных, но в последнее время много работаю над этим материалом. Я не знаю, что вы до сих пор прослушивали, но сначала вы захотите установить DataContext для вашего вида. Поскольку вы используете MVVM, я предполагаю, что у вас есть ViewModel, так что это должен быть DataContext для вашего вида.

т.е. если у вас есть View create / владелец вашей ViewModel, она может выглядеть следующим образом:

MyViewModel vm = new MyViewModel();
this.DataContext = vm;

Вы легко можете создать базу данных CheckBox, ComboBox и TextBox для свойств в вашей ViewModel. Я нашел самый простой способ заставить вашу ViewModel наследовать от базового класса ViewModel, как , который написал Джош Смит. Это даст вам метод для внутреннего вызова, когда вы хотите, чтобы ViewModel уведомил GUI об изменении значений.

Если предположить, что у вас есть такие свойства, как ImportColumn, LastName и LastNameText (все свойства C#, а не поля, которые вызывают OnPropertyChanged соответственно), то ваш XAML будет выглядеть примерно так:

<CheckBox IsChecked="{Binding ImportColumn}" />
<ComboBox SelectedItem="{Binding LastName}" />
<TextBox Text="{Binding LastName Text, Mode=TwoWay}" />

Надеюсь, это вам поможет. Если нет, то, пожалуйста, прокомментируйте, и я постараюсь сделать все возможное, чтобы попробовать другие вещи.

0
ответ дан 5 December 2019 в 20:16
поделиться

В нашем приложении мы делаем нечто подобное.

То, что я сделал, основано на моем собственном типе столбца (DataGridSearchableBooleanColumn), затем я заменил шаблон DataGridColumnHeader, я поместил туда двух презентаторов контента. первый я привязываю к содержимому (так же, как шаблон по умолчанию), второй я привязываю к столбцу. Я использую шаблон данных для столбца (у меня их несколько для разных типов поиска (текст, комбинированный, логический). Затем я добавляю дополнительные свойства в столбец, чтобы я мог к ним привязаться. Посмотрите, имеет ли этот код смысл.

   <!--Style for the datagrid column headers, contains a text box for searching-->
   <Style
      x:Key="columnHeaderStyle"
      TargetType="dg:DataGridColumnHeader">
      <Setter
         Property="Foreground"
         Value="#FF000000" />
      <Setter
         Property="HorizontalContentAlignment"
         Value="Left" />
      <Setter
         Property="VerticalContentAlignment"
         Value="Center" />
      <Setter
         Property="IsTabStop"
         Value="False" />
      <Setter
         Property="Padding"
         Value="1,2,1,2" />
      <Setter
         Property="Template">
         <Setter.Value>
            <ControlTemplate
               TargetType="dg:DataGridColumnHeader">
               <Grid
                  x:Name="Root">
                  <dg:DataGridHeaderBorder
                     Background="{TemplateBinding Background}"
                     BorderBrush="{TemplateBinding BorderBrush}"
                     BorderThickness="{TemplateBinding BorderThickness}"
                     Padding="{TemplateBinding Padding}"
                     IsClickable="{TemplateBinding CanUserSort}"
                     IsHovered="{TemplateBinding IsMouseOver}"
                     IsPressed="{TemplateBinding IsPressed}"
                     SeparatorBrush="{TemplateBinding SeparatorBrush}"
                     SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
                     SortDirection="{TemplateBinding SortDirection}">

                     <Grid
                        HorizontalAlignment="Stretch"
                        Margin="{TemplateBinding Padding}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                        <Grid.Resources>
                           <DataTemplate
                              DataType="{x:Type local:DataGridSearchableBooleanColumn}">
                              <CheckBox
                                 Margin="0,5,0,0"
                                 IsThreeState="True"
                                 IsChecked="{Binding Path=IsChecked}" />
                           </DataTemplate>
                        </Grid.Resources>
                        <Grid.ColumnDefinitions>
                           <ColumnDefinition />
                           <ColumnDefinition
                              Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                           <RowDefinition
                              Height="19" />
                           <RowDefinition
                              Height="Auto" />
                        </Grid.RowDefinitions>

                        <ContentPresenter
                           Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, Path=Content}" />

                        <Path
                           x:Name="SortIcon"
                           Fill="#FF444444"
                           Stretch="Uniform"
                           HorizontalAlignment="Left"
                           Margin="4,0,0,0"
                           VerticalAlignment="Center"
                           Width="8"
                           Opacity="0"
                           RenderTransformOrigin=".5,.5"
                           Grid.Column="1"
                           Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z ">
                           <Path.RenderTransform>
                              <ScaleTransform
                                 ScaleX=".9"
                                 ScaleY=".9" />
                           </Path.RenderTransform>
                        </Path>
                        <ContentPresenter
                           x:Name="columnHeaderContentPresenter"
                           Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Column}"
                           Grid.Row="1"
                           Grid.ColumnSpan="2"
                           Margin="0,0,0,0" />
                     </Grid>
                  </dg:DataGridHeaderBorder>

                  <Thumb
                     x:Name="PART_LeftHeaderGripper"
                     HorizontalAlignment="Left">
                     <Thumb.Style>
                        <Style
                           TargetType="{x:Type Thumb}">
                           <Setter
                              Property="Width"
                              Value="8" />
                           <Setter
                              Property="Background"
                              Value="Transparent" />
                           <Setter
                              Property="Cursor"
                              Value="SizeWE" />
                           <Setter
                              Property="Template">
                              <Setter.Value>
                                 <ControlTemplate
                                    TargetType="{x:Type Thumb}">
                                    <Border
                                       Background="{TemplateBinding Background}"
                                       Padding="{TemplateBinding Padding}" />
                                 </ControlTemplate>
                              </Setter.Value>
                           </Setter>
                        </Style>
                     </Thumb.Style>
                  </Thumb>
                  <Thumb
                     x:Name="PART_RightHeaderGripper"
                     HorizontalAlignment="Right">
                     <Thumb.Style>
                        <Style
                           TargetType="{x:Type Thumb}">
                           <Setter
                              Property="Width"
                              Value="8" />
                           <Setter
                              Property="Background"
                              Value="Transparent" />
                           <Setter
                              Property="Cursor"
                              Value="SizeWE" />
                           <Setter
                              Property="Template">
                              <Setter.Value>
                                 <ControlTemplate
                                    TargetType="{x:Type Thumb}">
                                    <Border
                                       Background="{TemplateBinding Background}"
                                       Padding="{TemplateBinding Padding}" />
                                 </ControlTemplate>
                              </Setter.Value>
                           </Setter>
                        </Style>
                     </Thumb.Style>
                  </Thumb>
               </Grid>
            </ControlTemplate>
         </Setter.Value>
      </Setter>
   </Style>
0
ответ дан 5 December 2019 в 20:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: