问题
Using VS 2010 I plan to make several datagrid template columns, but they will all contain a textblock and I want to them to behave like a text column in terms of sorting, filtering, editing, etc. (For example, a column that has a textblock and an image within a stackpanel, but behavior-wise it should really be all about the text.)
When using a template column, I've learned that much of the functionality associated with a normal text cell must be redone. For instance, in order to make the text editable, one must provide a cell editing template like:
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox
FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"
Text="{Binding Path=SomeProperty, Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
(And you must also handle grid events in order to make sure it behaves like a normal textbox, like automatically beginning edit mode if the user presses a key down, or tabs to the cell, etc.)
So my question is, what is the best way (if any) for me to avoid having to explicitly write this code (as well as the code for sorting, copying, filtering, etc like a textcell, for EVERY template column I create like this? I'm assuming it's bad practice to be reproducing half a page's worth of code for each column, where the only differences might the binded property name and a handful of visual alterations.
I am beyond frustrated with this, and with WPF in general. I've scoured the web, I've tried adorners, I've tried inheriting a datagrid column, I've tried defining user controls for the data templates, and everything seems to fail with some nasty "gotcha". This is about the 3rd question I've asked regarding this with varying details, with minimal response. It should NOT be this hard to figure out how to implement what are basically glorified text columns, without needing to reinvent the entire wheel every single time and in every single respect. In my humble opinion at least.
回答1:
can you show me how use cell styles to modify an existing DataGridTextColumn such that it displays text along with an image next to it?
Here:
<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>
With some more work, you can define these templates and style as Resources
in your application and reuse them every time.
With regards to the image source, you could use an Attached Property
to define it in the DataGridTextColumn
, or even the Tag
property.
Edit: Example with an attached property:
<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>
Code:
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;
}
}
回答2:
Create a library project, add the code and markup, and the reference this new dll from the projects.
来源:https://stackoverflow.com/questions/17663625/how-to-reuse-a-custom-datagrid-column-code-in-wpf