WPF 通用 DataGrid CellTemplate - 绑定到单元格值?

发布于 2024-07-19 03:57:16 字数 1470 浏览 5 评论 0原文

我在理解 WPF 中数据绑定的基础知识时遇到问题。 我有一个通用的 DataGrid(设置了 AutoGenerateColumns),它绑定到一个 DataTable,其列名随每次加载而变化。 当 dataTable 包含布尔类型的列时,我想渲染一个包含表示 true 和 false 的自定义图像的列。

为了实现此目的,我在单元模板的页面上声明了一个 StaticResource,并且我有捕获 AutoGenerateColumn 事件并使用此模板的 C# 代码:

<DataTemplate x:Key="CheckmarkColumnTemplate">
    <Image x:Name="CheckmarkImage" Source="..\..\images\check.png" Height="16" Width="16" />
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value}" Value="False">
            <Setter TargetName="CheckmarkImage" Property="Source" Value="..\..\images\nocheck.png" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

C# 代码:

private void dgData_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyType == typeof(bool))
    {
        DataGridTemplateColumn col = new DataGridTemplateColumn();
        Binding binding = new Binding(e.PropertyName);
        col.CellTemplate = (this.Resources["CheckmarkColumnTemplate"] as DataTemplate);
        col.Header = e.PropertyName;
        e.Column = col;
    }
}

这大部分都有效,只是我的 DataTrigger Binding 属性搞砸了。 它永远不会检测列的值何时为“false”,因此它永远不会显示 nocheck.png 图像。 我不知道如何编写 Binding 属性,以便引用列的数据绑定值(请记住,列名称每次都不同,因此我无法在绑定的 Path 部分中对列名称进行硬编码) 。

谁能告诉我 Binding 属性应该是什么样子,以便它只获取列的值?

I'm having a problem understanding the basics of databinding in WPF. I have a generic DataGrid (with AutoGenerateColumns set) that is bound to a DataTable with column names that vary on every load. When the dataTable contains columns that are of type boolean, I want to render a column that contains custom images representing true and false.

To accomplish this, I have a StaticResource declared on the page for the celltemplate, and I have c# code that traps the AutoGenerateColumn event and uses this template:

<DataTemplate x:Key="CheckmarkColumnTemplate">
    <Image x:Name="CheckmarkImage" Source="..\..\images\check.png" Height="16" Width="16" />
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value}" Value="False">
            <Setter TargetName="CheckmarkImage" Property="Source" Value="..\..\images\nocheck.png" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

C# code:

private void dgData_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyType == typeof(bool))
    {
        DataGridTemplateColumn col = new DataGridTemplateColumn();
        Binding binding = new Binding(e.PropertyName);
        col.CellTemplate = (this.Resources["CheckmarkColumnTemplate"] as DataTemplate);
        col.Header = e.PropertyName;
        e.Column = col;
    }
}

This mostly works, except I've got the DataTrigger Binding property messed up. It never detects when the value of the column is "false", so it never shows the nocheck.png image. I don't know how to write the Binding property so that's referencing the databound value of the column (remember, the column name is different every time, so I can't hard-code a column name in the Path part of the binding).

Can anyone tell me what the Binding property should look like so that it just grabs the value of the column?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木落 2024-07-26 03:57:16

我有同样的问题,仍在寻找答案。 我当前的解决方案是在 AutoGenerateColumn 事件处理程序中创建 DataTemplate ,以便 DataTemplate 知道属性名称。

private void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    e.Column = new DataGridTemplateColumn
    {
        Header = e.PropertyName,
        CellTemplate = CreateSimpleCellTemplate(e.PropertyName)
    }
}

private static DataTemplate CreateSimpleCellTemplate(string propertyName)
{
    DataTemplate template = new DataTemplate();
    template.VisualTree = new FrameworkElementFactory(typeof(Label));
    template.VisualTree.SetBinding(ContentProperty, new Binding(propertyName));
    return template;
}

I am having the same problem and still looking for an answer. My current solution is to create the DataTemplate in AutoGeneratingColumn event handler so the DataTemplate knows the property name.

private void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    e.Column = new DataGridTemplateColumn
    {
        Header = e.PropertyName,
        CellTemplate = CreateSimpleCellTemplate(e.PropertyName)
    }
}

private static DataTemplate CreateSimpleCellTemplate(string propertyName)
{
    DataTemplate template = new DataTemplate();
    template.VisualTree = new FrameworkElementFactory(typeof(Label));
    template.VisualTree.SetBinding(ContentProperty, new Binding(propertyName));
    return template;
}
一影成城 2024-07-26 03:57:16

我通过使用不同的方法达到了我想要的结果。 我没有使用 DataGridTemplateColumn,而是使用了 DataGridCheckBoxColumn 并根据 WPF 工具包的“动手实验室”中使用的示例样式设置了自定义 ElementStyle:

<Style x:Key="NoBorderCheckBoxStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="{StaticResource CheckBoxFillNormal}"/>
    <Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="IsEnabled" Value="false"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
                    <BulletDecorator.Bullet>
                        <Canvas x:Name="canvas"  Width="16" Height="16" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5">
                            <Image x:Name="checkImage" Source="..\..\images\check.png" Height="16" Width="16"></Image>
                        </Canvas>
                    </BulletDecorator.Bullet>
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
                </BulletDecorator>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasContent" Value="True">
                        <Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
                        <Setter Property="Padding" Value="4,0,0,0"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="False">
                        <Setter Property="Source" TargetName="checkImage" Value="..\..\images\nocheck.png" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我在从实际 DataGrid 列设置(其属性)读取“IsEnabled”属性时遇到问题是“IsReadOnly”),但因为我使用的 DataGrid 是只读的,所以我在这里将其设置为 false。

I achieved the result I was after by using a different method. Instead of using a DataGridTemplateColumn, I used a DataGridCheckBoxColumn and set a custom ElementStyle based off the sample style used in the WPF Toolkit's "Hands-On Lab":

<Style x:Key="NoBorderCheckBoxStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="{StaticResource CheckBoxFillNormal}"/>
    <Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="IsEnabled" Value="false"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
                    <BulletDecorator.Bullet>
                        <Canvas x:Name="canvas"  Width="16" Height="16" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5">
                            <Image x:Name="checkImage" Source="..\..\images\check.png" Height="16" Width="16"></Image>
                        </Canvas>
                    </BulletDecorator.Bullet>
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
                </BulletDecorator>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasContent" Value="True">
                        <Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
                        <Setter Property="Padding" Value="4,0,0,0"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="False">
                        <Setter Property="Source" TargetName="checkImage" Value="..\..\images\nocheck.png" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I had problems reading the "IsEnabled" property from the actual DataGrid column settings (its property is "IsReadOnly") but because my use of the DataGrid is read-only, I just set it to false here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文