【问题标题】:How to reuse a custom datagrid column code in WPF?如何在 WPF 中重用自定义数据网格列代码?
【发布时间】:2013-07-15 20:46:30
【问题描述】:

使用 VS 2010 我计划制作几个 datagrid 模板列,但它们都将包含一个文本块,我希望它们在排序、过滤、编辑等方面表现得像一个文本列。(例如,一个列它在堆栈面板中有一个文本块和一个图像,但在行为方面它应该是关于文本的。)

在使用模板列时,我了解到与普通文本单元格相关的大部分功能必须重做。例如,为了使文本可编辑,必须提供一个单元格编辑模板,如:

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <TextBox
        FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"
        Text="{Binding Path=SomeProperty, Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
            </TextBox>
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

(并且你还必须处理网格事件以确保它的行为像一个普通的文本框,比如如果用户按下一个键,或者单元格的标签等自动开始编辑模式.)

所以我的问题是,什么是最好的方法(如果有的话)我可以避免显式编写此代码(以及用于排序、复制、过滤的代码,等像文本单元一样,对于我这样创建的每个模板列?我假设为每列复制半页的代码是不好的做法,唯一的区别可能是绑定的属性名称和少数视觉变化。

我对此感到非常沮丧,总体上对 WPF 也是如此。我搜索了网络,尝试了装饰器,尝试了继承数据网格列,尝试为数据模板定义用户控件,但一切似乎都因一些讨厌的“陷阱”而失败。这是关于我提出的第三个问题,其中有不同的细节,但反应很少。 应该很难弄清楚如何实现基本上是美化的文本列,而无需每次都在每个方面都重新发明整个轮子。至少在我看来。

【问题讨论】:

  • 你把事情复杂化了太多。为什么不直接为相关列设置CellStyle,然后覆盖DataGridCell.Template?您还可以将这些模板定义为资源并重用它们。这样一来,您就可以保留 DataGridTextColumn 而不必自己实现它。
  • 听起来不错——你能给我一些代码吗?例如,您能告诉我如何使用单元格样式来修改现有的DataGridTextColumn,使其旁边显示文本和图像吗?

标签: wpf datagrid datagridtemplatecolumn


【解决方案1】:

你能告诉我如何使用单元格样式来修改现有的 DataGridTextColumn,使其在旁边显示文本和图像吗?

这里:

 <DataGridTextColumn Binding="{Binding LastName}">
     <DataGridTextColumn.CellStyle>
         <Style TargetType="DataGridCell">
             <Setter Property="Template">
                 <Setter.Value>
                     <ControlTemplate TargetType="DataGridCell">
                         <Grid>
                             <Grid.ColumnDefinitions>
                                 <ColumnDefinition/>
                                 <ColumnDefinition Width="16"/>
                             </Grid.ColumnDefinitions>

                             <ContentPresenter ContentSource="Content"/>
                             <Image Source="/Images/Homer.jpg" Grid.Column="1"/>
                        </Grid>
                     </ControlTemplate>
                 </Setter.Value>
             </Setter>
         </Style>
     </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

再做一些工作,您可以在您的应用程序中将这些模板和样式定义为Resources,并且每次都重复使用它们。

关于图像源,您可以使用Attached PropertyDataGridTextColumn 甚至Tag 属性中定义它。

编辑:带有附加属性的示例:

 <DataGrid ...>
            <DataGrid.Resources>
                <ControlTemplate TargetType="DataGridCell" x:Key="TextAndImageDataGridCellTemplate">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="16"/>
                        </Grid.ColumnDefinitions>

                        <ContentPresenter ContentSource="Content"/>
                        <Image Source="{Binding Column.(local:GridColumnProperties.ImageSource), RelativeSource={RelativeSource TemplatedParent}}" Grid.Column="1"/>
                    </Grid>
                </ControlTemplate>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding LastName}"
                                    local:GridColumnProperties.ImageSource="/Images/Homer.jpg">
                    <DataGridTextColumn.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Setter Property="Template" Value="{StaticResource TextAndImageDataGridCellTemplate}"/>
                        </Style>
                    </DataGridTextColumn.CellStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
    </DataGrid>

代码:

   public static class GridColumnProperties
    {
        public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.RegisterAttached("ImageSource", typeof(ImageSource), typeof(GridColumnProperties), new PropertyMetadata());

        public static void SetImageSource(DependencyObject obj, ImageSource value)
        {
            obj.SetValue(ImageSourceProperty, value);
        }

        public static ImageSource GetImageSource(DependencyObject obj)
        {
            return obj.GetValue(ImageSourceProperty) as ImageSource;
        }
    }

【讨论】:

  • 为什么选择单元格时显示为空白?有什么办法让它仍然显示蓝色背景的内容?
  • @Tekito 由于您覆盖了默认的Template,因此您失去了默认的视觉行为。查看默认样式的最后一个 XAML here。您可以复制该模板并对其进行修改以包含我的代码。
  • 我会试一试。非常真诚地感谢您发布此信息。我的理智几乎没有了,试图弄清楚这一点。我毫不怀疑 WPF 是一个强大的工具,但它也是我遇到过的最棘手的工具之一,除非你能够花费大量时间来掌握它。
  • @Tekito 黄金的重量是值得的。相信我,你会喜欢的。
  • 您可能不再阅读此内容,但我坚持使用 AttachedProperty 来定义图像源。它是快速简单的,还是更复杂的?
【解决方案2】:

创建一个库项目,添加代码和标记,并从项目中引用这个新的 dll。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 2011-11-08
  • 2013-08-11
  • 2021-01-03
  • 1970-01-01
  • 2015-08-23
相关资源
最近更新 更多