嵌套的WFC DataGrid给出NullReferenceException

时间:2012-07-13 14:44:37

标签: c# wpf datagrid

我有三层深度的树状对象结构,并试图在DataGrid中表示它。

我将在下面展示XAML,但基本上有一个顶级DataGrid,其中DataGridTemplateColumn包含一个ToggleButton。如果单击该按钮,则会显示第二个DataGrid,它具有相同的设置。这应该允许您单击第二个网格中的ToggleButton并显示第三个(和最终的)DataGrid。

这是预期的结果:

enter image description here

因此,您点击“目的地...”以显示目标网格,然后点击“表达式...”以显示该详细信息。

两个按钮都使用相同的代码实现:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ToggleButton Content="Destinations..." ButtonBase.Click="ToggleButton_Click" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

如果两个按钮都分配了它们的Click处理程序(相同的处理程序或不同),当我单击“Destinations ...”(在目标网格甚至显示之前)时,我得到一个NullReferenceException。

但是,如果我拿出“表达式...”按钮的处理程序,一切都只显示花花公子,但当然你无法扩展内部网格。

问题不在于我的对象,因为如果我只是离开网格的RowDetailsVisibilityMode =“可见”数据来自所有三个级别反映在网格中。这个问题似乎与在内部网格上使用ButtonBase.Click事件隔离开来。

这是XAML:

<Window x:Class="SPConvert.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Stored Procedure Converter" Height="425" Width="705">
    <Grid>
        <DataGrid Name="conversionsGrid" RowDetailsVisibilityMode="Collapsed" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ToggleButton Content="Destinations..." ButtonBase.Click="ToggleButton_Click" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <StackPanel DockPanel.Dock="Left">
                        <Label Content="Add destination paths" />
                        <DataGrid ItemsSource="{Binding Destinations}" RowDetailsVisibilityMode="Visible">
                            <DataGrid.Columns>
                                <DataGridTemplateColumn>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <ToggleButton Content="Expressions..." ButtonBase.Click="ToggleButton_Click" />
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                            <DataGrid.RowDetailsTemplate>
                                <DataTemplate>
                                    <DataGrid ItemsSource="{Binding Expressions}" AutoGenerateColumns="True">
                                    </DataGrid>
                                </DataTemplate>
                            </DataGrid.RowDetailsTemplate>
                        </DataGrid>
                    </StackPanel>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
    </Grid>
</Window>

更新 我最初没有包含click处理程序的代码,因为那里不会发生异常。在调试时,我可以看到执行并返回有效行的Click(属于Destinations按钮)(并确认它是正确的行)。只要未分配内部按钮(表达式)的事件处理程序,该行就会扩展为花花公子。分配后,我收到错误。但请记住,表达式按钮永远不会被点击,我可以在调试器中确认处理程序只执行一次。

以下是点击处理程序的代码:

private DataGridRow FindClickedRow(DependencyObject dep)
{
    // dep is the DependencyObject that was clicked. We can then iterate up the visual tree to find the clicked row.
    while ((dep != null) && !(dep is DataGridRow))
        dep = VisualTreeHelper.GetParent(dep);
    return dep as DataGridRow;
}

private void ToggleButton_Click(object sender, RoutedEventArgs e)
{
    DataGridRow row = FindClickedRow(e.OriginalSource as DependencyObject);
    row.DetailsVisibility = (row.DetailsVisibility == Visibility.Collapsed)?Visibility.Visible:Visibility.Collapsed;
}

1 个答案:

答案 0 :(得分:3)

link描述了您的问题。

简单地说,您无法附加到RowDetailsTemplate中内联的事件表单模板。

第一个解决方案:将模板移动到Control \ Window Resources:

 <Window.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="innertemplate">
            <ToggleButton Content="Expressions..." ButtonBase.Click="ToggleButton_Click" />
        </DataTemplate>

        <DataTemplate x:Key="template">
            <StackPanel DockPanel.Dock="Left">
                <Label Content="Add destination paths" />
                <DataGrid ItemsSource="{Binding Destinations}" RowDetailsVisibilityMode="Visible">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn CellTemplate="{StaticResource innertemplate}">

                        </DataGridTemplateColumn>
                    </DataGrid.Columns>
                    <DataGrid.RowDetailsTemplate>
                        <DataTemplate>
                            <DataGrid ItemsSource="{Binding Expressions}" AutoGenerateColumns="True">
                            </DataGrid>
                        </DataTemplate>
                    </DataGrid.RowDetailsTemplate>
                </DataGrid>
            </StackPanel>
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>

并在网格中引用它:

RowDetailsTemplate="{StaticResource template}"

第二个解决方案:将模板内容移至UserControl并将模板添加为:

 <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <local:YourControl />

我的项目local

xmlns:local="clr-namespace:WpfApplication1"