【问题标题】:ContentTemplate Binding questionContentTemplate 绑定问题
【发布时间】:2011-11-03 10:57:12
【问题描述】:

我的应用程序中有来自 WPF Toolkit 的 DataGrid 控件。我需要用调整的 TextBlock 替换用于单元格的默认 TextBlock。 XAML 代码看起来像:

<Window.Resources>
    <Style x:Key="cellStyle" TargetType="{x:Type tk:DataGridCell}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <TextBlock Background="Yellow" />
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid>
    <tk:DataGrid
        ItemsSource="{Binding Path=Products}"
        CellStyle="{StaticResource cellStyle}"
        AutoGenerateColumns="False">
        <tk:DataGrid.Columns>
            <tk:DataGridTextColumn
                Header="Id"
                Binding="{Binding Path=Id}"/>
            <tk:DataGridTextColumn
                Header="Product"
                Binding="{Binding Path=Name}"/>
        </tk:DataGrid.Columns>
    </tk:DataGrid>
</Grid>

TextBlock 替换后,所有数据绑定丢失,所有单元格为空。将属性 Text="{Binding}" 添加到新的 TextBlock 没有帮助。在这种情况下,所有单元格都包含 DataGridTestApp.Product 类型的名称。 TextBlock 的正确绑定表达式是什么?

附:以防万一:MainWindowViewModel 的代码

internal sealed class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        _products = new ObservableCollection<Product>()
        {
            new Product(1, "ProductName1"),
            new Product(2, "ProductName2"),
            new Product(3, "ProductName3"),
            new Product(4, "ProductName4"),
            new Product(5, "ProductName5"),
        };
    }

    public ObservableCollection<Product> Products
    {
        get { return _products; }
    }

    private ObservableCollection<Product> _products;
}

【问题讨论】:

    标签: c# .net .net-3.5 datagrid wpftoolkit


    【解决方案1】:

    如果您查看工具包的源代码,您会发现数据网格单元格的现有样式(它使用内容呈现器来显示列)

      <Style x:Key="{x:Type dg:DataGridCell}" TargetType="{x:Type dg:DataGridCell}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type dg:DataGridCell}">
              <Border Background="{TemplateBinding Background}" 
                      BorderBrush="{TemplateBinding BorderBrush}"  
                      BorderThickness="{TemplateBinding BorderThickness}" 
                      SnapsToDevicePixels="True">
                <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
              </Border>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
        <Style.Triggers>
          <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
          </Trigger>
          <Trigger Property="IsKeyboardFocusWithin" Value="True">
            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static dg:DataGrid.FocusBorderBrushKey}}" />
          </Trigger>
        </Style.Triggers>
      </Style>
    

    为了得到你的黄色背景,我只需要替换

        <Setter Property="Background" Value="Transparent" />
    

        <Setter Property="Background" Value="Yellow" />
    

    如果你不顾一切地想要覆盖里面的 TextBlock,那么使用上面的模板,但是将它添加到边框内

    <Border.Resources>
      <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Margin" Value="0,5" />
        <Setter Property="Background" Value="Yellow" />
      </Style>
    </Border.Resources>
    

    【讨论】:

    • 谢谢。但这是我的问题的简化示例。实际上,我需要将 Margin 属性设置为“0,5”的 TextBlock。我可以为 DataGridCell 设置 Margin 属性,但对我来说不一样。行选择的外观会有所不同。
    • 设置contentpresenters padding/margin不会有同样的效果吗?
    • 在这种情况下,选择将不包括边距/填充。并且相邻的选择之间会有很大的差距。如果设置了 TextBlock 的 Margin 属性,问题就解决了。
    • 我终于来到了 ContentPresenter 解决方案。谢谢。
    【解决方案2】:

    TextBlock 的数据上下文是一个产品。如果是您要显示的产品名称,请使用:

    <Window.Resources>
        <Style x:Key="cellStyle" TargetType="{x:Type tk:DataGridCell}">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock Background="Yellow" Text="{Binding Name}" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    

    不幸的是,如果您覆盖模板,您将丢失在 DataGridTextColumn 中设置的所有绑定。

    【讨论】:

    • 在 Text="{Binding Name}" 的情况下,所有单元格都将包含产品名称,但单元格内容应取决于列。对于第一列,所有单元格都应显示产品 ID,对于第二列 - 产品名称。有可能吗?
    • 哦,我明白了。我认为就像 Bob Vale 所说,您应该使用 ContentPresenter。
    猜你喜欢
    • 2011-05-18
    • 2013-02-26
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    相关资源
    最近更新 更多