WPF在DataTemplate下对ItemsControl进行排序

时间:2014-04-11 07:33:17

标签: wpf wpf-4.0

我在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 个答案:

答案 0 :(得分:4)

您有两种选择:

1 - 在View Model中对源集合(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将显示已排序的项目。

答案 1 :(得分:0)

最后我解决了排序问题。 我将(observablecollection&lt; seg&gt;)绑定到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;

我没有直接生成,而是创建了另一个变量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;

生成所有值后,使用以下代码完成排序并分配到

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

它对我来说很好。