WPF:可以通过MultiValueConverter设置DataGridCell的内容吗?

时间:2022-03-23 00:27:19

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.

我有一个datagrid,它有几个静态和更动态生成的coloumns。使用多值转换器成功调整动态添加的coloumns单元的背景图像。现在我需要向这些单元格添加内容,而不仅仅是改变它们的背景。我希望使用多值转换器来实现这种目的,但它没有。在调试器中运行MultiValueConverter,它返回一个字符串,但单元格保持为空。

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.

请参阅代码,其中Backround设置正在运行但内容设置没有。除了gridCellBgConverter返回Brush之外,它们必须是相同的代码,gridCellContentConverter返回字符串。

<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 have idea how to try to solve this?

WPF的固有属性是无法通过Style和ValueConverter设置内容吗?你知道如何解决这个问题吗?

Thanks in advance: Ferenc

提前致谢:Ferenc

Kind of Solution

一种解决方案

With the help of AngelWPF I was able to solve my proplem:

在AngelWPF的帮助下,我能够解决我的问题:

  1. the dynamically created coloumns type are DataGridTemplateColoumn

    动态创建的coloumns类型是DataGridTemplateColoumn

  2. 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

而在MultiValueConverter而不是

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 :)

访问原始单元格。我毫不怀疑有更好的方法可以做到这一点,但它似乎工作:)

1 个解决方案

#1


0  

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...

关于这种方法的注意事项是你在这方面失去了许多Cell级功能,例如验证,编辑模式,背景颜色,鼠标悬停,选择颜色等......

I will still recommend using DataGridTemplate columns and CellTemplate property.

我仍然建议使用DataGridTemplate列和CellTemplate属性。

#1


0  

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...

关于这种方法的注意事项是你在这方面失去了许多Cell级功能,例如验证,编辑模式,背景颜色,鼠标悬停,选择颜色等......

I will still recommend using DataGridTemplate columns and CellTemplate property.

我仍然建议使用DataGridTemplate列和CellTemplate属性。