为了账号安全,请及时绑定邮箱和手机立即绑定

ItemsControl 包装问题

ItemsControl 包装问题

C#
慕码人2483693 2022-11-21 16:54:42
我做了一些小的自定义 ItemsControl 来将一些列表显示为项目行。它几乎完美地工作。<ItemsControl.ItemTemplate>    <DataTemplate>       <WrapPanel Orientation="Horizontal">           <TextBlock x:Name="delimiter" Text=";" Margin="0 0 5 0"/>           <TextBlock Text="{Binding LinkId}" />       </WrapPanel>       <DataTemplate.Triggers>          <DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">              <Setter Property="Visibility" TargetName="delimiter" Value="Collapsed"/>          </DataTrigger>        </DataTemplate.Triggers>    </DataTemplate></ItemsControl.ItemTemplate>我的问题在定界符中:当 ItemsConteol 换行到下一行时,定界符 char 会从下一行开始。我知道问题出在哪里,但我不知道如何解决。
查看完整描述

3 回答

?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

我有一个简单的解决方案DataTemplateSelector。它是这样的:


您定义一个选择器,用于区分最后一项。


class LastElementSelector : DataTemplateSelector

{

    public DataTemplate NormalTemplate { get; set; }

    public DataTemplate LastTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)

    {

        return IsLast(container) ? LastTemplate : NormalTemplate;

    }


    bool IsLast(DependencyObject container)

    {

        var itemsControl = FindParentOrSelf<ItemsControl>(container);

        var idx = itemsControl.ItemContainerGenerator.IndexFromContainer(container);

        var count = itemsControl.Items.Count;

        return idx == count - 1;

    }


    T FindParentOrSelf<T>(DependencyObject from) where T : DependencyObject

    {

        for (var curr = from; curr != null; curr = VisualTreeHelper.GetParent(curr))

            if (curr is T t)

                return t;

        return null;

    }

}

有了这个,您可以对普通项目和最后项目使用不同的模板:


<ItemsControl ItemsSource="{Binding}">

    <ItemsControl.ItemsPanel>

        <ItemsPanelTemplate>

            <WrapPanel IsItemsHost="True"/>

        </ItemsPanelTemplate>

    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplateSelector>

        <local:LastElementSelector>

            <local:LastElementSelector.NormalTemplate>

                <DataTemplate>

                    <TextBlock>

                        <Run Text="{Binding Mode=OneWay}"/><!-- no space between runs

                        --><Run Text="; " Foreground="Red" FontWeight="Bold"/>

                    </TextBlock>

                </DataTemplate>

            </local:LastElementSelector.NormalTemplate>

            <local:LastElementSelector.LastTemplate>

                <DataTemplate>

                    <TextBlock Text="{Binding}"/>

                </DataTemplate>

            </local:LastElementSelector.LastTemplate>

        </local:LastElementSelector>

    </ItemsControl.ItemTemplateSelector>

</ItemsControl>

结果:

https://i.stack.imgur.com/RIcQR.gif


查看完整回答
反对 回复 2022-11-21
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

您的定界符位于下一行的前面,因为它位于 LinkId TextBox 的前面,并且它们都在 WrapPanel 中绑定在一起。整个 WrapPanel 流向下一行。

WrapPanels 上方的父面板不知道也不关心其中的内容。

//img1.sycdn.imooc.com//637b3d0700012ba406530160.jpg

顺便说一下,我不知道这是否是您的意图,但在您编写的代码中,您为集合中的每个项目生成了一个不同的 WrapPanel。目前,您的测试列表中有 20 个 WrapPanel。


如果像您所说的那样,最后一个分隔符不是问题,那么这是一个足够好的解决方案:


    <ItemsControl

        ItemsSource="{Binding YourItems}"

        >

        <ItemsControl.ItemsPanel>

        <ItemsPanelTemplate>

            <WrapPanel

                Orientation="Horizontal"

                ></WrapPanel>

        </ItemsPanelTemplate>

        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>

            <DataTemplate>

                <StackPanel

                    Orientation="Horizontal"

                    >

                    <TextBlock

                        Text="{Binding LinkId}"

                        ></TextBlock>

                    <TextBlock

                        Text="; "

                        ></TextBlock>

                </StackPanel>

            </DataTemplate>

        </ItemsControl.ItemTemplate>

    </ItemsControl>

如果这仅用于数据显示目的,请考虑那些行中的文本框很可能是文本框内的单个字符串。也许您可以使用单一格式的字符串并将相关部分制作成链接。这会将操作的字符串分隔符部分移至 ViewModel,并会大大简化您的 XAML 代码。


查看完整回答
反对 回复 2022-11-21
?
翻阅古今

TA贡献1780条经验 获得超5个赞

您可以尝试将定界符放在文本之后,并通过将其属性设置为空字符串来隐藏最后一个Run元素:Text


<ItemsControl AlternationCount="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}">

    <ItemsControl.ItemsPanel>

        <ItemsPanelTemplate>

            <WrapPanel Orientation="Horizontal" />

        </ItemsPanelTemplate>

    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>

        <DataTemplate>

            <TextBlock>

                <Run Text="{Binding Path=., Mode=OneWay}" /><Run x:Name="delimiter" Text=";    "/>

            </TextBlock>

            <DataTemplate.Triggers>

                <Trigger Property="ItemsControl.AlternationIndex" Value="0">

                    <Setter Property="Text" TargetName="delimiter" Value=""/>

                </Trigger>

            </DataTemplate.Triggers>

        </DataTemplate>

    </ItemsControl.ItemTemplate>

</ItemsControl>

这应该使分隔符和文本保持在同一行。


查看完整回答
反对 回复 2022-11-21
  • 3 回答
  • 0 关注
  • 92 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信