在WPF中过滤绑定的XML数据

时间:2009-12-16 11:47:05

标签: c# wpf data-binding

基本上我有一个WPF应用程序,它会在列表框中向用户显示通知。填充列表框的信息来自XML文件,其中包含有关不同公告的详细信息。然后我应用数据模板来显示相关的信息。我所拥有的是应用程序底部的两个按钮,我想要的是当用户点击未读公告按钮时数据被过滤以仅显示列表框中的未读公告。然后,当用户点击所有公告时,我希望它们全部再次显示。无论点击哪个按钮,我使用的数据模板都将保持不变。

在正在使用的XML文件中有一个名为read的字段,0表示尚未读取,而1表示它已经读取,应该用于过滤。

所以我真的只是在寻找过滤或任何好教程的例子,所以我可以取得一些进展。如果您需要我的任何代码,请告诉我,我会将其粘贴。

修改

现在添加以下代码以显示数据的绑定方式以及数据布局:

<XmlDataProvider
                        x:Key="Article"
                        Source="/Data/People.xml"
                        XPath="People/article"/>
<DataTemplate x:Key="AnnouncementTemplate">
            <Border Background="#2200FF00" 
                            BorderBrush="Black" 
                            BorderThickness="1" 
                            CornerRadius="8"  
                            Margin="2,4,2,4" 
                            Padding="2"
                    >
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition Width="220"/>
                    </Grid.ColumnDefinitions>
                    <Border Background="#2200FF00" 
                            BorderBrush="Black" 
                            BorderThickness="1" 
                            CornerRadius="8"  
                            Margin="2,4,2,4" 
                            Padding="2"
                    >
                    <StackPanel Grid.Column="0">
                        <Image Stretch="Fill" Width="20" Source="Images/BlueOrb.ico" Height="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    </StackPanel>
                </Border>
                <StackPanel Grid.Column="1" Margin="5">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontWeight="Bold" Text="{Binding XPath=./author}" />
                        <TextBlock Text=" "/>
                        <TextBlock Text="{Binding XPath=./datetime}" TextTrimming="WordEllipsis"/>
                    </StackPanel>
                    <StackPanel>
                        <TextBlock FontWeight="Bold" Text="{Binding XPath=./title}"/>
                    </StackPanel>
                    <StackPanel>
                        <TextBlock Text="{Binding XPath=./body}" TextTrimming="WordEllipsis"/>
                    </StackPanel>
                 </StackPanel>

                </Grid>
            </Border>
        </DataTemplate>

<ListBox Style="{StaticResource SpecialListStyle}"
                         Name="listBox1"
                         Margin="10,10,10,10"
                         Grid.Row="1"
                         ItemsSource="{Binding Source={StaticResource Article}}" 
                         IsSynchronizedWithCurrentItem="True"
                         ItemContainerStyle="{StaticResource SpecialListItem}"
                         ItemTemplate="{StaticResource AnnouncementTemplate}"/>

XML文件中保存的数据示例,数据希望被过滤,因此它只显示read == 0

的消息
<People>
  <article>
    <author>Michael</author>
    <title>Happy Christmas</title>
    <body>Merry Christmas one and all</body>
    <priority>1</priority>
    <uid>G-0617-8567-EF32-hello</uid>
    <audience>0</audience>
    <read>0</read>
    <datetime>December 31, 2009 23:59:59</datetime>
  </article>
  <article>
    <author>Gary</author>
    <title>Landesk</title>
    <body>Landesk Distributed</body>
    <priority>0</priority>
    <uid>G-0618-8567-EF32-hello</uid>
    <audience>0</audience>
    <read>1</read>
    <datetime>December 31, 2009 23:59:59</datetime>
  </article>
</People>

2 个答案:

答案 0 :(得分:1)

将数据绑定到列表框或任何类似控件时,WPF会将其与CollectionViewSource实例包装在一起。

因此,假设您的数据源名为myItems。然后您可以按如下方式获取此实例:

ICollectionViewSource viewSource = CollectionViewSource.GetDefaultView(myItems);

ICollectionViewSource具有Filter属性,可用于过滤项目。您还可以使用ICollectionViewSource.Refresh()强制可视控件刷新其内容。

答案 1 :(得分:0)

我现在能够使用以下代码解决此问题,该代码还涉及将XML文件的读取节点转换为article元素的属性:

ICollectionView RefineList()
    {
        DataSourceProvider provider = (DataSourceProvider)this.FindResource("Article");
        return CollectionViewSource.GetDefaultView(provider.Data);
    }

        private void Unread_Click(object sender, RoutedEventArgs e)
    {
        ICollectionView view = RefineList();
         if (view.Filter == null)
        {
            view.Filter = delegate(object item)
            {
                return
                int.Parse(((XmlElement)item).Attributes["read"].Value) == 0;
            };
        }
        else
        {
            view.Filter = null;
        }   
    }