【问题标题】:WPF: Binding lists in XAML- how can an item know its position in the list?WPF:XAML 中的绑定列表 - 项目如何知道其在列表中的位置?
【发布时间】:2014-11-30 08:08:48
【问题描述】:

鉴于以下 XAML 代码具有类似 ListControl 的行为:

    <StackPanel>
        <ItemsControl Name="_listbox" ItemsSource="{Binding ElementName=_userControl, Path=DataContext}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <DockPanel>
                         ...
                    </DockPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>

由于列表可能很长(100-200 个项目),并且项目看起来相似,我认为如果每个项目都显示它们在列表中的位置,这将对用户在滚动过程中有所帮助。 模板中的项目如何知道自己在列表中的位置?

【问题讨论】:

    标签: wpf data-binding list xaml


    【解决方案1】:

    这是一个黑客解决方案。我们可以将值转换与 DataBinding 一起使用。所以第一步就是声明我们的ValueConvertor:

    public class ListItemToPositionConverter : IValueConverter
        {
            #region Implementation of IValueConverter
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var item = value as ListBoxItem;
                if (item != null)
                {
                    var lb = FindAncestor<ListBox>(item);
                    if (lb != null)
                    {
                        var index = lb.Items.IndexOf(item.Content);
                        return index;
                    }
                }
                return null;
            }            
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    
            #endregion
        }
    

    在任何你想要这个静态方法的地方声明以获得 ListBox 父级:

    public static T FindAncestor<T>(DependencyObject from) where T : class
            {
                if (from == null)
                    return null;
    
                var candidate = from as T;
                return candidate ?? FindAncestor<T>(VisualTreeHelper.GetParent(from));
            }
    

    然后在 ListBox.Resources 中声明我们的转换器如下:

    <ListBox.Resources>
                    <YourNamespace:ListItemToPositionConverter x:Key="listItemToPositionConverter"/>
                </ListBox.Resources>
    

    最后 - 数据模板:

    <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource listItemToPositionConverter}}"/>
                            <Label Content="{Binding Path=DisplayName}"></Label>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
    

    注意:在此示例中,项目将从 0(零)开始编号,您可以在 Convert 方法中通过将结果加 1 来更改它。

    希望这会有所帮助...

    【讨论】:

      【解决方案2】:

      根据MSDN Magazine文章“Charting with DataTemplates”:

      [...]DataTemplate 需要访问集合中特定数据项的索引。但是将这些信息包含在业务对象中很容易[...]

      因此,除非 .NET 4 发生变化,否则没有“此项的索引”属性,除非它明确包含在模型中。

      【讨论】:

        【解决方案3】:

        此示例支持排序:

        Numbered listbox

        【讨论】:

          猜你喜欢
          • 2019-09-05
          • 2022-01-16
          • 1970-01-01
          • 1970-01-01
          • 2019-02-21
          • 2017-12-11
          • 2019-05-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多