WPF数据模板下的ItemsControl排序

3

我正在使用DataTemplate下的ItemsControl。我希望按照id列对ItemsControl ic 进行排序。

   <DataTemplate x:Key="With">
        <DockPanel>               
            <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
                <TextBlock Text="{Binding Path=fil}" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
                <mui:ModernButton  IconData="{StaticResource PlayIconData}" Click="FullPlayback" Margin="0,0,6,8" ></mui:ModernButton>
            </StackPanel>
            <StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
                <TextBlock Text="{Binding Path=e1}" Foreground="Red" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
                <TextBlock Text="{Binding Path=m1}" Foreground="LightSalmon" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
                <TextBlock Text="{Binding Path=n1}" Foreground="Orange" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
                <TextBlock Text="{Binding Path=m2}" Foreground="LightGreen" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
                <TextBlock Text="{Binding Path=m3}" Foreground="Green" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
                <TextBlock Text="{Binding ElementName=H1, Path=Items.Count,Mode=OneWay}" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
            </StackPanel>

            <ItemsControl Name="ic" DockPanel.Dock="Bottom" ItemsSource="{Binding Path=seg}" ItemsPanel="{StaticResource HSPanel}">              
                    <ControlTemplate TargetType="ItemsControl"> 
                        <Border>
                            <ScrollViewer VerticalScrollBarVisibility="Auto">
                                <ItemsPresenter />
                            </ScrollViewer>
                        </Border>
                    </ControlTemplate>
                </ItemsControl.Template>
            </ItemsControl>
        </DockPanel>
    </DataTemplate>

我可以帮您翻译成中文:

我尝试了以下选项,但排序无法正常工作。

1. 尝试在用户控件的构造函数中进行排序,如下所示(代码后台)

ic.Items.SortDescriptions.Clear();
ic.Items.SortDescriptions.Add(new SortDescription("id", ListSortDirection.Ascending));
ic.Items.Refresh();

但是我无法在代码后端访问ic。错误显示“ic不存在于当前上下文中”

2.尝试在xaml中的ItemsControl下使用CollectionViewSource也不起作用。

<ItemsControl x:Name="ic" DockPanel.Dock="Bottom" ItemsSource="{Binding Path=segments}" ItemsPanel="{StaticResource HSPanel}">
             <ItemsControl.Resources>
                            <CollectionViewSource x:Key="segments"  Source="{Binding seg}">
                                <CollectionViewSource.SortDescriptions>
                                    <scm:SortDescription PropertyName="id" Direction="Ascending"/>
                                </CollectionViewSource.SortDescriptions>
                            </CollectionViewSource>
                        </ItemsControl.Resources>
                <ItemsControl.Template>

3. 尝试在XAML的ControlTemplate中使用CollectionViewSource,但也没有起作用。

                    <ControlTemplate TargetType="ItemsControl">                            
                            <ControlTemplate.Resources>
                                <CollectionViewSource x:Key="segments" Source="{Binding seg}" >
                                    <CollectionViewSource.SortDescriptions>
                                        <scm:SortDescription PropertyName="sortId" Direction="Ascending"/>
                                    </CollectionViewSource.SortDescriptions>
                                </CollectionViewSource>
                        </ControlTemplate.Resources>

但是我初始化了ic的Loaded事件,并尝试从那里进行排序。在这种情况下,当页面加载时,项目没有排序。但是当我切换到另一个用户控件并返回到当前用户控件时,项目看起来已经完美地排序了。
    private void ic_Loaded(object sender, RoutedEventArgs e)
    {
        ItemsControl ic = (ItemsControl)sender;
        ic.Items.SortDescriptions.Clear();
        ic.Items.SortDescriptions.Add(new SortDescription("id", ListSortDirection.Ascending));
        ic.Items.Refresh();
    }
2个回答

8

您有两个选项:

1- 在视图模型中对源集合(seg)进行排序。

2- 使用CollectionViewSource (http://msdn.microsoft.com/fr-fr/library/system.windows.data.collectionviewsource.aspx)。以下是一个完整的工作示例:

我已将此代码添加到一个空WPF窗口中:

public class SomeVM
{
    public ObservableCollection<SomeItemVM> Items { get; set; }

    public SomeVM()
    {
        Items = new ObservableCollection<SomeItemVM>();
    }
}

public class SomeItemVM
{
    public string id { get; set; }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        //Create some VM
        SomeVM data = new SomeVM();
        data.Items.Add(new SomeItemVM() { id = "3" });
        data.Items.Add(new SomeItemVM() { id = "4" });
        data.Items.Add(new SomeItemVM() { id = "1" });
        data.Items.Add(new SomeItemVM() { id = "2" });

        this.DataContext = data;
    }

}

然后在XAML中,我添加了一个内容控件来承载VM和一个DataTemplate来描述VM的显示方式:

<Window.Resources>

    <DataTemplate x:Key="With">
        <DockPanel>
            <DockPanel.Resources>
                <!-- CollectionViewSource should be declared as a resource of parent container of the ItemsControl. 
                     Otherwise there will be an exception of StaticResourceHolder --> 
                <CollectionViewSource x:Key="segments" Source="{Binding Items}">
                    <CollectionViewSource.SortDescriptions>
                        <scm:SortDescription PropertyName="id" Direction="Ascending"/>
                    </CollectionViewSource.SortDescriptions>
                </CollectionViewSource>
            </DockPanel.Resources>

            <ItemsControl Name="ic" DockPanel.Dock="Bottom" ItemsSource="{Binding Source={StaticResource segments}}">

                <ItemsControl.Template>
                    <ControlTemplate TargetType="ItemsControl">
                        <Border>
                            <ScrollViewer VerticalScrollBarVisibility="Auto">
                                <ItemsPresenter />
                            </ScrollViewer>
                        </Border>
                    </ControlTemplate>
                </ItemsControl.Template>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding id}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DockPanel>
    </DataTemplate>

</Window.Resources>

<Grid>

    <ContentControl Content="{Binding}" ContentTemplate="{StaticResource With}"/>

</Grid>

生成的ItemsControl会显示已排序的项。

抱歉,我忘了提到我也尝试了你的选项。 - senthilraja
实际上它是可以工作的,但我忘记将CollectionViewSource放入父容器的资源中,因此它会抛出StaticResourceHolder异常。我已经更新了答案,并提供了完整的代码。 - Dmitry
它对我没用。我在按钮点击时加载ObservableCollection并绑定到ItemsControl。 顺便问一下,为什么无法在代码后台访问ItemsControls ic?我一点头绪也没有。 - senthilraja
不确定这是否有帮助,但我通过在DataTemplate上添加x:Shared=True使其工作。在我的情况下,我有一个需要使用CollectionViewSource的itemscontrol。这非常有用。 - TravisWhidden

0

最终我解决了排序问题。 我正在将段落(observablecollection< seg>)绑定到itemscontrol。以前,在代码后台中,我直接生成以下段落

segments[0].name="GHI";
segments[0].age=40;
segments[1].name="ABC";
segments[1].age=20;
segments[2].name="DEF";
segments[2].age=30;

我没有直接生成segments,而是创建了另一个变量objSegments,并按以下方式生成值。

objSegments[0].name="GHI";
objSegments[0].age=40;
objSegments[1].name="ABC";
objSegments[1].age=20;
objSegments[2].name="DEF";
objSegments[2].age=30;

在生成所有值之后,使用以下代码进行排序并分配给segments

        ObservableCollection<seg> sortedSegments = new ObservableCollection<seg>(objSegments.OrderBy(c => c.id));
        foreach (var objSeg in sortedSegments)
        {
            segments.Add(objSeg);
        }

对我来说它运行得很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接