0

我的目标是在 WPF 数据网格列中创建一个就地编辑器来编辑大文本。

我的数据源是一个 DataTable,它可以包含来自不同表和字段的数据,这就是为什么我没有任何定义的类型可以绑定。在我的示例中,它有 1 个名为“Test”的列。现在我编写了一些 XAML 代码来定义我的列:

<ControlTemplate x:Key="ExtendedTemplate">
    <StackPanel>
        <TextBox Text="{Binding Test}" Width="200" Height="100" AcceptsReturn="True" TextWrapping="Wrap"/>
    </StackPanel>
</ControlTemplate>                

<DataGrid x:Name="grid" ItemsSource="{Binding}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="TEST Column" Width="200">
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox IsDropDownOpen="True">
                        <ComboBoxItem Template="{StaticResource ExtendedTemplate}"/>
                    </ComboBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Test}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

这是我的测试数据源:

Source = new DataTable("Test");
Source.Columns.Add("Test");
Source.Rows.Add("Item 1 - large amount of text ...");
Source.Rows.Add("Item 2");
Source.Rows.Add("Item 3");
grid.DataContext = Source;

这很好用,但我需要做的最后一件事是在网格单元处于编辑模式时装饰网格单元,并且我在扩展组合中输入文本:

截屏

这很重要:首先 - 组合框未绑定到任何 ItemsSource,但任何单元格都存在单个 ComboBoxItem 并包含来自该单元格的文本。

第二 - 我无法将 DataTemplate 定义为 SelectedItem,因为 ComboBox.SelectionBoxItemTemplate 属性是只读的。

有谁知道我怎样才能将 SelectionBoxItem 的数据模板替换为这样的东西?

<DataTemplate>
    <TextBlock Text="{Binding Test}"/>
</DataTemplate>

我尝试使用命令“编辑模板 - 编辑副本...”为组合框创建自定义样式。有很多标记,我不想在这里发布。这是我编辑的一小部分。

<ContentPresenter ContentTemplate="{StaticResource SimplestTemplate}" 
                  ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 
                  Content="{TemplateBinding SelectionBoxItem}" 
                  ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"
                  IsHitTestVisible="false"
                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                  VerticalAlignment="Stretch"
                  HorizontalAlignment="Stretch"/>

它不起作用,因为 id 不知道如何编写应该将数据绑定到我的“测试”字段的“简单模板”。

4

1 回答 1

0

我通过创建一种派生自ComboBox并覆盖其ContentPresenter ContentTemplate. 它工作正常,但我停止了我的工作,因为有许多额外的功能需要实现(例如调整弹出编辑器的大小、自动刷新网格单元格、将命令分配给热键以仅使用键盘编辑器等) . 最后我决定使用第三方组件(这个)。

作为对我的问题的回答,我发布了我的最终 XAML 标记:

资源:

<Window.Resources>

    <DataTemplate x:Key="SimplestTemplate">
        <Grid>
            <TextBlock Background="White" Foreground="Black" Text="{TemplateBinding Content}"/>
        </Grid>
    </DataTemplate>

    <ControlTemplate x:Key="ExtendedTemplate">
        <StackPanel>
            <TextBox Text="{Binding Test}" MinHeight="100" Height="Auto" MinWidth="{TemplateBinding Width}" Width="{Binding MinWidth}" TextWrapping="Wrap"/>
        </StackPanel>
    </ControlTemplate>                

    <Style x:Key="MyComboBoxStyle" TargetType="{x:Type ComboBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ComboBox}">
                    <Grid x:Name="MainGrid" SnapsToDevicePixels="true">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
                        </Grid.ColumnDefinitions>
                        <Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
                            <Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
                                <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
                                    <ScrollViewer x:Name="DropDownScrollViewer">
                                        <Grid RenderOptions.ClearTypeHint="Enabled">
                                            <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                                <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
                                            </Canvas>
                                            <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                        </Grid>
                                    </ScrollViewer>
                                </Border>
                            </Themes:SystemDropShadowChrome>
                        </Popup>
                        <ContentPresenter ContentTemplate="{StaticResource SimplestTemplate}"
                                          ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 
                                          Content="{TemplateBinding help:ComboboxHelper.BindedText}" 
                                          ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"                                               
                                          IsHitTestVisible="false"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                          VerticalAlignment="Stretch"
                                          HorizontalAlignment="Stretch"
                                          Grid.ColumnSpan="2"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>      
</Window.Resources>

网格列模板:

<DataGridTemplateColumn Header="TEST Column" Width="200">
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox IsDropDownOpen="True" Style="{StaticResource MyComboBoxStyle}" FocusVisualStyle="{x:Null}" help:ComboboxHelper.BindedText="{Binding Test}">
                <ComboBoxItem Template="{StaticResource ExtendedTemplate}"/>
            </ComboBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Test}" TextTrimming="CharacterEllipsis"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

为了在单元格中显示剪切的文本,我创建了一个简单的附加属性。它会剪切"\n"文本中的所有符号以使其成为单行。

public static class ComboboxHelper
{
    public static readonly DependencyProperty BindedTextProperty = DependencyProperty.RegisterAttached("BindedText", typeof(string), typeof(ComboboxHelper));

    public static string GetBindedText(DependencyObject obj)
    {
        string s = (string)obj.GetValue(BindedTextProperty);
        s = s.Replace(Environment.NewLine, " ");
        return s;
    }

    public static void SetBindedText(DependencyObject obj, string value)
    {
        obj.SetValue(BindedTextProperty, value);
    }
}
于 2013-01-27T17:50:42.287 回答