【问题标题】:DataGrid Column Header with filter box binding error带有过滤器框绑定错误的 DataGrid 列标题
【发布时间】:2016-12-15 11:51:48
【问题描述】:

尝试了几天后,我将我的项目精简到最低限度,以便将其附加到我的问题中。

我想在我的 WPF 数据网格标题中添加一个文本过滤器框。 但我收到以下错误消息:

System.Windows.Data Error: 40 : BindingExpression path error: 'TextFilterData' property not found on 'object' ''DataGridColumnHeader' (Name='PART_FillerColumnHeader')'. BindingExpression:Path=TextFilterData; DataItem='DataGridColumnHeader' (Name='PART_FillerColumnHeader'); target element is 'TextBox' (Name='PART_TextFilter'); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'TextFilterData' property not found on 'object' ''DataGridColumnHeader' (Name='')'. BindingExpression:Path=TextFilterData; DataItem='DataGridColumnHeader' (Name=''); target element is 'TextBox' (Name='PART_TextFilter'); target property is 'Text' (type 'String')

我的应用程序中的数据网格:

<Grid>
    <local:MyDataGrid x:Name="myDataGrid">
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Width="64"
                                Binding="{Binding Path=id, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, FallbackValue=''}"
                                local:DataGridColumnExtensions.TextFilterData="{Binding Path=FilterId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                <DataGridTextColumn.HeaderStyle>
                    <Style TargetType="DataGridColumnHeader" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
                        <Setter Property="ToolTip" Value="The ID of the person"/>
                    </Style>
                </DataGridTextColumn.HeaderStyle>
            </DataGridTextColumn>

            <!-- The filter data will be replaced by property binding in the real application. Here I'm using a fix value for the sake of simplicity -->
            <DataGridTextColumn Header="Name" Width="400"
                                Binding="{Binding Path=name, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, FallbackValue=''}"
                                local:DataGridColumnExtensions.TextFilterData="{Binding Path=FilterName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                <DataGridTextColumn.HeaderStyle>
                    <Style TargetType="DataGridColumnHeader" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
                        <Setter Property="ToolTip" Value="The name of the person"/>
                    </Style>
                </DataGridTextColumn.HeaderStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </local:MyDataGrid>
</Grid>

我正在使用扩展类为文本过滤器内容创建依赖属性

public class DataGridColumnExtensions
{
    public static readonly DependencyProperty TextFilterDataProperty = DependencyProperty.RegisterAttached("TextFilterData", typeof(string), typeof(DataGridColumn), new FrameworkPropertyMetadata(String.Empty));
    public static string GetTextFilterData(DependencyObject target)
    {
        return (string)target.GetValue(TextFilterDataProperty);
    }
    public static void SetTextFilterData(DependencyObject target, string value)
    {
        target.SetValue(TextFilterDataProperty, value);
    }
}

这是我正在使用的数据网格样式。为了简单起见,我尝试删除所有不需要的内容。

<Style TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1" Background="Gray" BorderBrush="DarkGray" Grid.ColumnSpan="2" />
                    <ContentPresenter Margin="3" VerticalAlignment="Center" />
                    <Path x:Name="SortArrow" Visibility="Collapsed" Data="M0,0 L1,0 0.5,1 z" Stretch="Fill" Grid.Column="1" Width="8" Height="6" Fill="White" Margin="0,0,8,0" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" />
                    <TextBox x:Name="PART_TextFilter"
                            Grid.Row="1" Margin="1,0,1,4"
                            Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}}, Path=Column.TextFilterData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                    <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource Style_HeaderGripper}"/>
                    <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource Style_HeaderGripper}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="SortDirection" Value="{x:Null}">
                        <Setter TargetName="BackgroundBorder" Property="Background" Value="Transparent" />
                        <Setter TargetName="BackgroundBorder" Property="BorderBrush"  Value="Transparent" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="BackgroundBorder" Property="Background" Value="LightGray" />
                        <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="Gray" />
                    </Trigger>
                    <Trigger Property="SortDirection" Value="Ascending">
                        <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                        <Setter TargetName="SortArrow" Property="RenderTransform">
                            <Setter.Value>
                                <RotateTransform Angle="180" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="SortDirection" Value="Descending">
                        <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type local:MyDataGrid}">
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyDataGrid}">
                <Border Background="{TemplateBinding Background}">
                    <ScrollViewer Focusable="false" Name="DG_ScrollViewer">
                        <ScrollViewer.Template>
                            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                        <RowDefinition Height="Auto"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>
                                    <Border Grid.ColumnSpan="3" Background="Gray" BorderBrush="DarkGray" BorderThickness="0,1" />
                                    <Button Command="{x:Static DataGrid.SelectAllCommand}" Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=RowHeaderActualWidth}" Focusable="false" OverridesDefaultStyle="True"/>
                                    <DataGridColumnHeadersPresenter Grid.Column="1"                         
                                                                    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, 
                                                                                         Path=HeadersVisibility, 
                                                                                         Converter={x:Static DataGrid.HeadersVisibilityConverter},
                                                                                         ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>
                                    <ScrollContentPresenter Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />
                                </Grid>
                            </ControlTemplate>
                        </ScrollViewer.Template>
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsGrouping" Value="true">
            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
        </Trigger>
    </Style.Triggers>
</Style>

让过滤器内容绑定工作缺少什么? 非常感谢任何帮助。


2016-08-10:首次修复更新

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    在 Header ControlTemplate 中,您在 TextBox 内使用 RelativeSource Self

    <TextBox x:Name="PART_TextFilter" 
       ...
       Text="{Binding RelativeSource={RelativeSource Self}, Path=TextFilterData, ...}"/>
    

    错误消息指出此 TextBox 上没有 TextFilterData 属性。

    试试

    Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}}, 
                   Path=Column.TextFilterData, ...}"/>
    

    【讨论】:

    • 是的,这也是我的原始版本,但我在玩的时候改变了它。抱歉,我没有改回来,因为AncestorType={x:Type DataGridColumnHeader} 更有意义。我更新了我上面的问题,但它仍然不起作用。
    • @Carpi 没问题,你注意到我也改变了路径吗?附加属性位于 DataGridColumn,而不是 DataGridColumnHeader。
    • 酷,这确实解决了我的问题。非常感谢您的大力帮助:o)
    • 完美运行。但是,当我现在在我的数据网格中为过滤器值使用绑定时,如上面更新的代码所示,然后我收到此错误消息:A 'Binding' cannot be set on the 'SetTextFilterData' property of type 'DataGridTextColumn'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.。有关如何解决此问题的任何线索?
    • 小附加信息。抛出的异常是Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 2011-12-22
    • 2015-01-02
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    相关资源
    最近更新 更多