动态填充WPF DataGrid

时间:2011-06-28 19:04:36

标签: c# wpf dynamic datagrid formatting

我的程序需要通过串行连接从火警面板获取输入,并根据它填充列表。从面板报告新设备时,将解析该语句,并将设备添加到设备列表中。

我程序的那部分都运行得很好,花花公子。现在的问题是向用户显示火警设备列表。

我希望使用DataGrid来实现这一点(除非有更好的方法吗?)但是我无法在与我相关的WPF DataGrids上找到很多有用的文档。大部分内容似乎都是从数据库中显示数据。但是,每当面板吐出新的设备描述并且附加了我的程序中的设备列表时,我需要更新。

我看到我可以将AutoGenerateColumns设置为true,并且最初显示我的列表就好了。但是,我想自定义列标题。当附加List时,这也不会更新,因此我不确定如何“刷新”它。

当AutoGenerateColumns为false时,我没有显示任何数据。程序运行时,它会显示与列表中项目数相对应的正确行数,但没有数据。想知道如何/如果我需要将每个列与其对应的设备数据成员链接?

最后,如何通过重新调整大小来格式化DataGrid?我可以设置列宽和所有这些,但我想要的是一些要固定宽度的列,以及要扩展以填充剩余可用区域的中间列。

这是我第一次尝试WPF。任何帮助将不胜感激!

5 个答案:

答案 0 :(得分:3)

Personaly我不喜欢DataGrid。是的,它们更容易绑定,它们提供内置的调整大小和排序选项,但它们不像在对象上具有良好DataTemplating的ItemsControl那样灵活。让我解释一下自己。

我倾向于使用ObservableCollection填充我的ItemsControl。然后,我使用DataTemplate告诉我的ItemsControl如何显示我的自定义项目。

如果你在做MVVM,你的CustomObjects可以是Modeles对象。 如果您的列表绑定到ObservableCollection,则添加和删除的项目将动态显示在您的列表中,这是我相信您的尝试。 对于列大小,您可以将Grid指定GridColumns宽度设置为某些列的固定宽度,将*设置为其他列,以便填充剩余空间。

这是GridView的替代方案 我在ItemControl周围使用ScrollViewer,所以如果ItemsControl太大,你可以滚动它。 ItemsControl的ItemSource绑定到FireAlarms的ObservableCollection。 ItemsControl中的WrapPanel将包含每个DataTemplate。它的宽度是绑定到他的父(或祖先,如果你愿意),这是一个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放在windows的ressource或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一样的表中,你可以使用面向verticaly的堆栈面板修改它,并使用一个具有可变//不变列宽的网格,但是因为你要求任何有用的东西,我很难惹你一些有趣的事情!

享受!

答案 1 :(得分:1)

这就是很多问题!我建议你在提问之前先做一些背景研究。我建议您阅读我之前写的关于WPF DataGrid的这篇代码项目文章:

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

它将为您回答大部分问题!

答案 2 :(得分:1)

一段时间后我写了一篇帖子Create DataGrid in WPF using code看看它,它会帮助你在像你这样的动态场景中创建数据网格

答案 3 :(得分:1)

如果你是一个动态网格(意思是列的数量和设计在设计时是未知的),我会使用带有绑定的代码隐藏。我通常使用MVVM模式(如果你不熟悉它,我真的建议你阅读它,因为它是使用WPF时的模式)。

1)您必须将自动生成列设置为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));

所以这也有效。 要记住的另一件事是删除列。这需要一些额外的工作。

答案 4 :(得分:0)

看看MVVM模式,在创建此应用程序时,这将是一个巨大的帮助。

你想要的是ViewModel中的ObservableCollection。您将datagrid的ItemsSource属性绑定到此集合。然后让您的列绑定到各种属性以显示它们。只要此ObservableCollection附加了一个项目,您的前端就会自动更新。

要使列自动调整大小,请设置宽度=“*”。

以下是MVVM数据网格的示例

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

在您继续努力的同时,针对每个问题发布单独的问题。