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

发布于 2024-11-27 22:25:29 字数 6203 浏览 3 评论 0原文

我有一个数据网格,其中有几个静态和更动态生成的列。动态添加的列单元格的背景图像已通过多值转换器成功调整。现在我需要向这些单元格添加内容,而不仅仅是更改它们的背景。我希望为此目的使用多值转换器也能起作用,但事实并非如此。 在调试器中,MultiValueConverter 运行,它返回一个字符串,但单元格保持为空。

请查看代码,其中背景设置有效,但内容设置无效。它们本质上是相同的代码,除了 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> 

难道WPF的固有属性就是Content不能通过Style和ValueConverter设置吗? 您知道如何尝试解决这个问题吗?

提前致谢: Ferenc

解决方案类型

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

  1. 动态创建的列类型是DataGridTemplateColoumn

  2. 样式设置器是:

    
    <设置器.值>
        <数据模板>
            
                <文本块>
                                                                       
                    
                        
                            <绑定RelativeSource="{RelativeSource Self}">
                            <绑定路径=“。” UpdateSourceTrigger="PropertyChanged">
                            <绑定路径=“TrainToAnnounceViewModel.SelectedStationIndex”UpdateSourceTrigger=“PropertyChanged”>
                            <绑定路径=“TrainToAnnounceViewModel.TrainOnTrackElementId”UpdateSourceTrigger=“PropertyChanged”>
                            ;
                            <绑定路径=“TrainToAnnounceViewModel.SelectedStationDelay”UpdateSourceTrigger=“PropertyChanged”>
                        
                    
                
                
            
        
    
    

在 MultiValueConverter 中,

public object Convert(object[] values,
       Type targetType, object parameter,
       CultureInfo culture) {
         var cell = (DataGridCell)values[0];

我必须使用

public object Convert(object[] values,
       Type targetType, object parameter,
       CultureInfo culture) {
          var textBlock = (TextBlock)values[0];
          var cell = (DataGridCell)((ContentPresenter)textBlock.TemplatedParent).TemplatedParent

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

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

  1. the dynamically created coloumns type are 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

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

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

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

发布评论

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

评论(1

像你 2024-12-04 22:25:29

假设您的数据网格是只读的(不可编辑),可以按如下方式实现。

(下面的代码未经测试)

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

这种方法的注意事项是您会失去许多单元级功能,例如验证、编辑模式、背景颜色、鼠标悬停、选择颜色等...

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

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.

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