如何强制wpf文本框的内容在其他控件上方类似于Excel单元的其他控件上方显示

发布于 2025-02-12 12:02:41 字数 705 浏览 2 评论 0 原文

我有一个ItemScontrol,其中包含每个绑定项目的文本框,如果其内容宽,则允许叠加文本框内容,而不是类似于Excel单元格覆盖行为的文本框宽度。 有办法这样做吗?

“

<ItemsControl ItemsSource="{Binding Path=MyCollection}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" Width="100"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}" TextWrapping="WrapWithOverflow"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

I have an ItemsControl that contains a textbox for each binding item and I want to allow overlaying text box content if its content is wider than the textbox width similar to excel cells overlaying behavior.
Is there a way to do this?

1

<ItemsControl ItemsSource="{Binding Path=MyCollection}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" Width="100"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}" TextWrapping="WrapWithOverflow"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

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

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

发布评论

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

评论(3

屌丝范 2025-02-19 12:02:41

您可以使用工具提示。您只需要自己绑定源即可。

<ListView ItemsSource="{Binding Path=MyStringCollection}">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" Width="100"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}" TextWrapping="WrapWithOverflow" ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

有关更多信息:

You can use tooltip for that. You just need to bind the source with itself.

<ListView ItemsSource="{Binding Path=MyStringCollection}">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" Width="100"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding}" TextWrapping="WrapWithOverflow" ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

For further information:

DrawToolTip Event

Set ToolTipSize

别想她 2025-02-19 12:02:41

要复制类似的行为,您可以使用弹出式

要实现类似的行为,您首先必须禁用 textbox 的内容包装。
然后用 textblock 替换当前 textbox ,该>用于显示文本。
弹出实际上包含Editable textbox ,然后将 textblock 叠加在确切位置,从而隐藏 textblock 使其似乎伸展和覆盖相邻的项目。
MultiTrigger 将在焦点移动 ListBoxItem 之外后立即关闭弹出窗口。

为了提高性能,您应该将 virtualizingstackpanel 用作项目。

<ListView ItemsSource="{Binding MyStringCollection}"
          HorizontalAlignment="Left"
          Width="800">
  <ListView.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>
  </ListView.ItemsPanel>

  <ListView.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Border BorderThickness="1"
                BorderBrush="Gray">
          <TextBlock Text="{Binding}" />
        </Border>
        <Popup x:Name="EditableTextSiteHost"
               PlacementTarget="{Binding ElementName=TextSite}"
               Placement="Relative"
               Height="{Binding ElementName=TextSite, Path=ActualHeight}"
               AllowsTransparency="True"
               FocusManager.FocusedElement="{Binding ElementName=EditableTextSite}">
          <TextBox x:Name="EditableTextSite"
                   Text="{Binding TextData}" />
        </Popup>
      </Grid>

      <DataTemplate.Triggers>
        <MultiDataTrigger>
          <MultiDataTrigger.Conditions>
            <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"
                       Value="True" />
            <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsKeyboardFocusWithin}"
                       Value="True" />
          </MultiDataTrigger.Conditions>
          <Setter TargetName="EditableTextSiteHost"
                  Property="IsOpen"
                  Value="True" />
        </MultiDataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ListView.ItemTemplate>

  <ListView.ItemContainerStyle>
    <Style TargetType="ListBoxItem">

      <!-- Make items overlap -->
      <Setter Property="Margin"
              Value="-2,0,0,0" />
      <Setter Property="Padding"
              Value="0" />
      <Setter Property="Width"
              Value="50" />

      <Style.Triggers>

        <!-- Apply zero Margin on the first item -->
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}"
                     Value="{x:Null}">
          <Setter Property="Margin"
                  Value="0,0,0,0" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ListView.ItemContainerStyle>
</ListView>

托而言,

这只是一个原始的例子,是概念证明。您必须改善行为。例如,当用户滚动或移动 window 时,您需要关闭弹出。否则,由于弹出本身是窗口,因此 popup 不会移动以遵循放置目标。您可以将相关逻辑移至附件的行为。
您可能还想改善选择行为。当前,选择突出显示边框(实际上)并未扩展到围绕弹出窗口。您必须通过在 textbox 上应用边框来模仿此功能,该边框将复制 ListBoxItem 突出显示边框。

To replicate a similar behavior, you can make use of a Popup.

To implement a similar behavior, you first must disable content wrapping of your TextBox.
Then replace the current TextBox with a TextBlock, which is used to display the text.
The Popup, which actually contains the editable TextBox, will then overlay this TextBlock at the exact position, thus hiding the TextBlock to make it appear to stretch and overlay the adjacent items.
A MultiTrigger will close the Popup as soon as the focus moved outside the ListBoxItem.

To improve performance you should use the VirtualizingStackPanel as items host.

<ListView ItemsSource="{Binding MyStringCollection}"
          HorizontalAlignment="Left"
          Width="800">
  <ListView.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>
  </ListView.ItemsPanel>

  <ListView.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Border BorderThickness="1"
                BorderBrush="Gray">
          <TextBlock Text="{Binding}" />
        </Border>
        <Popup x:Name="EditableTextSiteHost"
               PlacementTarget="{Binding ElementName=TextSite}"
               Placement="Relative"
               Height="{Binding ElementName=TextSite, Path=ActualHeight}"
               AllowsTransparency="True"
               FocusManager.FocusedElement="{Binding ElementName=EditableTextSite}">
          <TextBox x:Name="EditableTextSite"
                   Text="{Binding TextData}" />
        </Popup>
      </Grid>

      <DataTemplate.Triggers>
        <MultiDataTrigger>
          <MultiDataTrigger.Conditions>
            <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"
                       Value="True" />
            <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsKeyboardFocusWithin}"
                       Value="True" />
          </MultiDataTrigger.Conditions>
          <Setter TargetName="EditableTextSiteHost"
                  Property="IsOpen"
                  Value="True" />
        </MultiDataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ListView.ItemTemplate>

  <ListView.ItemContainerStyle>
    <Style TargetType="ListBoxItem">

      <!-- Make items overlap -->
      <Setter Property="Margin"
              Value="-2,0,0,0" />
      <Setter Property="Padding"
              Value="0" />
      <Setter Property="Width"
              Value="50" />

      <Style.Triggers>

        <!-- Apply zero Margin on the first item -->
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}"
                     Value="{x:Null}">
          <Setter Property="Margin"
                  Value="0,0,0,0" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ListView.ItemContainerStyle>
</ListView>

To-do

This is just a raw example, a proof of concept. You would have to improve the behavior. For example, you would want to close the Popup when the user scrolls or moves the Window. Otherwise, since Popup itself is a Window, the Popup would not move to follow the placement target. You could move the related logic to an attached behavior.
You likely also want to improve the selection behavior. Currently the selection highlight border does not (virtually) extend to surround the Popup. You have to mimic this by applying a Border on the TextBox that will replicate the ListBoxItem highlight border.

隔岸观火 2025-02-19 12:02:41

我通过使用此助手依赖属性 https://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-count-properties/ 作为itemscontrol的容器模板项目索引和绑定网格。Zindex与相邻文本框上方显示的反向索引。

<ItemsControl ItemsSource="{Binding MyCollection}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Grid HorizontalAlignment="Left" helpers:GridHelpers.ColumnCount="{Binding MyCollection.Count}"/>
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="Grid.Column" Value="{Binding ItemIndex}"/>
        <Setter Property="Grid.ZIndex" Value="{Binding ReversedIndex}" />
        <Setter Property="Grid.ColumnSpan" Value="{Binding MaxMergedCells}" />
    </Style>
  </ItemsControl.ItemContainerStyle>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <TextBox MinWidth="30" Text="{Binding }"/>
        </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>

I managed to produce the excel cells overlay behavior by using a Grid with dynamic column count using this helper dependency properties https://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-properties/ as a container template of ItemsControl and binding the column index of each textbox to the ordered item index and binding Grid.ZIndex to the reversed index to be displayed above the adjacent text boxes.

<ItemsControl ItemsSource="{Binding MyCollection}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Grid HorizontalAlignment="Left" helpers:GridHelpers.ColumnCount="{Binding MyCollection.Count}"/>
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="Grid.Column" Value="{Binding ItemIndex}"/>
        <Setter Property="Grid.ZIndex" Value="{Binding ReversedIndex}" />
        <Setter Property="Grid.ColumnSpan" Value="{Binding MaxMergedCells}" />
    </Style>
  </ItemsControl.ItemContainerStyle>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <TextBox MinWidth="30" Text="{Binding }"/>
        </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文