Заполнить WPF DataGrid динамически - PullRequest
0 голосов
/ 28 июня 2011

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

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

Я надеюсь сделать это с помощью DataGrid (если нет лучшего способа?), Но не могу найти много полезной документации поWPF DataGrids, что актуально для меня.Большая часть того, что там есть, кажется, отображает данные из базы данных.Мой, однако, должен обновляться каждый раз, когда на панели появляется новое описание устройства и добавляется список устройств в моей программе.

Я вижу, что могу установить AutoGenerateColumns в true и изначально отображать мой список просто отлично.НО, я хотел бы настроить заголовки столбцов.Также это не обновляется, когда список добавляется, поэтому я не уверен, как его «обновить».

Когда AutoGenerateColumns имеет значение false, данные не отображаются.Когда программа запускается, она показывает мне правильное количество строк, соответствующее количеству элементов в моем списке, но без данных.Хотите знать, как / если мне нужно связать каждый столбец с соответствующим элементом данных устройства?

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

Это мой первый удар в WPF.Любая помощь будет принята с благодарностью!

Ответы [ 5 ]

3 голосов
/ 29 июня 2011

Лично я не очень люблю DataGrid.Да, их проще связывать, и они предлагают встроенные параметры изменения размера и сортировки, но они не так гибки, как ItemsControl, с хорошим DataTemplating для ваших объектов.Позвольте мне объяснить.

Я стремлюсь заполнить свой ItemsControl ObservableCollection.Затем я использую DataTemplate, чтобы сообщить своему ItemsControl, как отображать мои пользовательские элементы.

Ваши объекты CustomObject могут быть объектами Modeles, если вы используете MVVM.Если ваш список привязан к коллекции ObservableCollection, добавленные и удаленные элементы будут динамически появляться в вашем списке, и я верю, что вы пытаетесь это сделать.Для размера столбца вы можете поместить Grid с указанием ширины GridColumns к фиксированной ширине для некоторых столбцов и * для других, чтобы они заполняли оставшееся пространство.

Вот альтернатива GridView. Я использую ScrollViewer вокруг моего ItemControl, поэтомуесли ItemsControl становится слишком большим, вы можете прокрутить его.ItemSontrol ItemsControl связан с ObservableCollection вашего FireAlarms.WrapPanel в ItemsControl будет содержать каждый шаблон данных.Это ширина привязана к его родителю (или предку, если хотите), который является ItemsControl

<ScrollViewer
    Grid.Row="x"
    Grid.Column="y"
    VerticalScrollBarVisibility="Auto"
    Margin="5">

    <ItemsControl
    BorderBrush="DarkBlue"
    BorderThickness="2"
    ItemsSource="{Binding Path=FireAlarms}"
    ItemTemplate="{StaticResource FireAlarmsTemplate}"
    >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel 
                        Orientation="Horizontal"
                        Width="{Binding RelativeSource=
                            {RelativeSource FindAncestor,
                            AncestorType={x:Type ItemsControl}},
                            Path=ActualWidth}"
                        >
                </WrapPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</ScrollViewer>

Хорошо, тогда вам нужен DataTemplate.Вы можете поместить DataTemplate в ресурсы вашего окна или в DataDictionnary.Допустим, у вас есть класс:

FireAlarm
{
    Public String AlarmInfo1;
    Public String AlarmInfo2;
    Public String AlarmInfo3;
}

Вот хороший пример DataTemplate, с которого можно начать:

<DataTemplate x:Key="FireAlarms">
    <Border 
        BorderBrush="SteelBlue" 
        Background="LightBlue" 
        BorderThickness="2" 
        Margin="10" 
        Padding="10">
        <StackPanel 
            Orientation="Vertical"
            >
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition Width="5"></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>


                <Label 
                    Grid.ColumnSpan="3"
                    Grid.Row="0"
                    Content="{Binding Path=AlarmName}"
                    Margin="5,-5,5,10"
                    FontWeight="Bold"
                    FontSize="16"
                    HorizontalContentAlignment="Center"
                    HorizontalAlignment="Center">
                </Label>

                <TextBlock  
                    Text="Alarm information 1" Grid.Row="1" Grid.Column="0" />
                <TextBox 
                    Text="{Binding Path=AlarmInfo1}"
                    Grid.Column="2"
                    Grid.Row="1"
                    >
                </TextBox>

                <TextBlock 
                    Text="Alarm information 2" Grid.Row="2" Grid.Column="0" />
                <TextBox 
                    Text="{Binding Path=AlarmInfo2}"
                    Grid.Column="2"
                    Grid.Row="2"
                    >
                </TextBox>

                <TextBlock  
                    Text="Alarm information 3" Grid.Row="3" Grid.Column="0" />
                <TextBox 
                    Text="{Binding Path=AlarmInfo3}"
                    Grid.Column="2"
                    Grid.Row="3"
                    >
                </TextBox>
            </Grid>
        </StackPanel>
    </Border>
</DataTemplate>

Хорошо, надеюсь, это полезно для вас.Мой шаблон будет генерировать 1 квадрат на тревогу.Если бы вы предпочли иметь его в таблице, такой как GridView, вы можете изменить это, используя вертикально ориентированную панель стека, и использовать сетку с переменной // неизменяемой шириной столбца, но, поскольку вы попросили что-нибудь полезное, я бы вас обманул.что-то интересное для работы!

Наслаждайтесь!

1 голос
/ 29 июня 2011

Если у вас динамическая сетка (имеется в виду, что число и дизайн столбцов неизвестны во время разработки), я делаю это с помощью кода с привязкой. Обычно я использую шаблон MVVM (если вы не знакомы с этим, я очень рекомендую прочитать его, поскольку это шаблон THE при работе с WPF).

1) Конечно, вы должны установить для Auto-Generate столбцы значение false и дать сетке имя (здесь myDataGrid)

GridViewDataColumn newColumn= new GridViewDataColumn();
myDataGrid.Columns.Add(newColumn)

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

 newColumn.Binding = new Binding("knownPropertyName");

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

 myDoubleCollection.Add(someDoubleValue); //do this for each item in the itemssource of the grid
   int index=myDoubleCollection.Count-1;
   newColumn.Binding = new Binding(string.Format("myDoubleCollection[{0}]",index));

Так что это тоже работает. Еще одна вещь, которую нужно иметь в виду, это удаление столбцов. Это требует дополнительной работы.

1 голос
/ 28 июня 2011

Некоторое время назад я написал сообщение Создание DataGrid в WPF с использованием кода посмотрите на него, это поможет вам в создании сетки данных в динамических сценариях, подобных вашему

1 голос
/ 28 июня 2011

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

http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx

Он ответит на большинство ваших вопросов для вас!

0 голосов
/ 28 июня 2011

Взгляните на шаблон MVVM , это очень поможет при создании этого приложения.

То, что вы хотите - это ObservableCollection во ViewModel. Вы свяжете свойство ItemsSource сетки данных с этой коллекцией. Затем ваши столбцы будут привязаны к различным свойствам для их отображения. Всякий раз, когда к этому ObservableCollection добавляется элемент, ваш интерфейс должен обновляться автоматически.

Для автоматического изменения размера столбца установите Width = "*".

Вот образец таблицы данных с MVVM

<DataGrid ItemsSource="{Binding FireAlarmCollection}" SelectedItem="{Binding SelectedFireAlarm, Mode=TwoWay}" AutoGenerateColumns="True" CanUserSortColumns="True" HorizontalScrollBarVisibility="Visible" CanUserResizeColumns="True">
</DataGrid>

Продолжая свои усилия, опубликуйте отдельные вопросы для каждой проблемы.

...