WPF: Can DataGridCell's content be set via MultiValueConverter?
I have a datagrid which has several static and more dynamicaly generated coloumns. The background image of the dynamically added coloumns' cells are successfuly adjusted with a multivalue converter. Now I need to add content to these cell not only change their backgound. I hoped that using a multivalue converter for this purpuse would work as well but it didn't. In debugger the MultiValueConverter runs, it returns with a string but the cells remain empty.
Please see the code, where Backround setting is working but Content setting doesn't. They are essentialy the same code except gridCellBgConverter returns Brush, gridCellContentConverter returns string.
<DataGrid DockPanel.Dock="Top" Name="main_dg" HorizontalAlignment="Stretch" HorizontalScrollBarVisibility="Hidden" Margin="3"
AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell"
SelectedCellsChanged="main_dg_SelectedCellsChanged" CanUserReorderColumns="False"
CanUserAddRows="False" CellEditEnding="main_dg_CellEditEnding" KeyUp="main_dg_KeyUp"
FontSize="14" FontWeight="Normal" FontStretch="Normal" SnapsToDevicePixels="True" TextOptions.TextFormattingMode="Display" RenderOptions.EdgeMode="Aliased">
<DataGrid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource gridCellBgConverter}" UpdateSourceTrigger="PropertyChanged">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}"></Binding>
<Binding Path="." UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.SelectedStationIndex" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.TrainOnTrackElementId" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.LastStationCountDownChanged" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.SelectedStationDelay" UpdateSourceTrigger="PropertyChanged"></Binding>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="Content">
<Setter.Value>
<MultiBinding Converter="{StaticResource gridCellContentConverter}" UpdateSourceTrigger="PropertyChanged">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}"></Binding>
<Binding Path="." UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.SelectedStationIndex" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.TrainOnTrackElementId" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.LastStationCountDownChanged" UpdateSourceTrigger="PropertyChanged"></Binding>
<Binding Path="TrainToAnnounceViewModel.SelectedStationDelay" UpdateSourceTrigger="PropertyChanged"></Binding>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
Is WPF's inherent property that Content can't be set through Style and ValueConverter? Do you h开发者_高级运维ave idea how to try to solve this?
Thanks in advance: Ferenc
Kind of Solution
With the help of AngelWPF I was able to solve my proplem:
the dynamically created coloumns type are DataGridTemplateColoumn
The style setter is:
<Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock> <TextBlock.Text> <MultiBinding Converter="{StaticResource gridCellContentConverter}" UpdateSourceTrigger="PropertyChanged"> <MultiBinding.Bindings> <Binding RelativeSource="{RelativeSource Self}"></Binding> <Binding Path="." UpdateSourceTrigger="PropertyChanged"></Binding> <Binding Path="TrainToAnnounceViewModel.SelectedStationIndex" UpdateSourceTrigger="PropertyChanged"></Binding> <Binding Path="TrainToAnnounceViewModel.TrainOnTrackElementId" UpdateSourceTrigger="PropertyChanged"></Binding> <Binding Path="TrainToAnnounceViewModel.LastStationCountDownChanged" UpdateSourceTrigger="PropertyChanged"></Binding> <Binding Path="TrainToAnnounceViewModel.SelectedStationDelay" UpdateSourceTrigger="PropertyChanged"></Binding> </MultiBinding.Bindings> </MultiBinding> </TextBlock.Text> </TextBlock> </StackPanel> </DataTemplate> </Setter.Value>
and in the MultiValueConverter instead of
public object Convert(object[] values,
Type targetType, object parameter,
CultureInfo culture) {
var cell = (DataGridCell)values[0];
i had to use
public object Convert(object[] values,
Type targetType, object parameter,
CultureInfo culture) {
var textBlock = (TextBlock)values[0];
var cell = (DataGridCell)((ContentPresenter)textBlock.TemplatedParent).TemplatedParent
the access the originating cell. I have no doubt that there are planty of better methods to do this, but it seems working :)
Assuming that your data grid is readonly (not editable), this can be implemented as below..
(The code below is not tested)
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
SnapsToDevicePixels="True">
<TextBlock>
<TextBlock.Text>
<!-- Your MultiBinding Here -->
</TextBlock.Text>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Caution about this approach is that you loose many Cell level functionalities in this such as validation, edit mode, background color, mouseover, selection color etc...
I will still recommend using DataGridTemplate columns and CellTemplate property.
精彩评论