Automatically filter/order ListBox items (Windows

2019-03-05 22:48发布

问题:

I want to ensure, that the items added in my list box are ordered in ascending order according to the serial number of each item (e.g 1 item, 2 item, 4 item, 3 item should be automatically order according to its number 1.2.3.......10).

Here is the C# source:

namespace XeroQuiz
{

   public partial class MainPage : PhoneApplicationPage
   {
     IsolatedStorageFile Settings1 = IsolatedStorageFile.GetUserStoreForApplication();
     MyDataList listobj = new MyDataList();

     public MainPage()
     {
        InitializeComponent();
        this.Loaded += MainPage_Loaded;
        this.FavoriteListBox.Visibility = Visibility.Collapsed;
        if (Settings1.FileExists("MyStoreItems"))
        {
            using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Open))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataList));
                listobj = (MyDataList)serializer.ReadObject(fileStream);

            }
        }
        FavoriteListBox.ItemsSource = listobj;//binding isolated storage list data

        DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.5) };
        timer.Tick += delegate (object sender, EventArgs e)
        {
            // var sortedList = listobj.OrderBy(item => item.AnswerName).ToList(); code is correct but no item is sorted in list.
            this.FavoriteListBox.ItemsSource = listobj;
            this.FavoriteListBox.UpdateLayout();
        };
        timer.Start();
    }


    /**************************************************************************/

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        if (Settings1.FileExists("MyStoreItems"))//loaded previous items into list
        {
            using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Open))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataList));
                listobj = (MyDataList)serializer.ReadObject(fileStream);
            }
        }
    }


    private void FavoriteButton_Click(object sender, RoutedEventArgs e)
    {
        if (listobj.Any(l => l.AnswerName == AnswerTextBlock.Text))
            return;
        //var sortedList = listobj.OrderBy(item => item.ToString()).ToList();
        listobj.Add(new MyData { AnswerName = AnswerTextBlock.Text });

        using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Create))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataList));
            serializer.WriteObject(fileStream, listobj);

        }
    }


    private void FavoriteRemoveButton_Click(object sender, RoutedEventArgs e)
    {
        lsitobj.Remove(listobj.FirstOrDefault(l => l.AnswerName == AnswerTextBlock.Text));

        using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Create))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataList));
            serializer.WriteObject(fileStream, listobj);

        }
    }
}



    private void FavoriteListButton_Click(object sender, RoutedEventArgs e)
    {
        if (FavoriteListBox.Visibility.Equals(Visibility.Collapsed))
        {
            FavoriteListBox.Visibility = Visibility.Visible;               
        }
        else if (FavoriteListBox.Visibility.Equals(Visibility.Visible))
        {
            FavoriteListBox.Visibility = Visibility.Collapsed;
        }
    }




    public class MyData
    {
        public string AnswerName { get; set; }
    }
    public class MyDataList : ObservableCollection<MyData>//for storing mydata class items with type of list
    {

    }


    private void FavoriteListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        MyData selecteddata = (sender as ListBox).SelectedItem as MyData;            
        if (selecteddata != null)
        {
            FavoritedData.Text = selecteddata.FrequencyName.ToString();
            using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MySelectedStoreItem", FileMode.Create))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(MyData));
                serializer.WriteObject(fileStream, selecteddata);
            }                
        }
    }
}

Here is the XAML code:

    <StackPanel Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top">                
        <ListBox x:Name="FavoriteListBox" Visibility="Collapsed" 
                 SelectionChanged="FavoriteListBox_SelectionChanged"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Top" Opacity="1"
                 Background="{StaticResource PhoneBackgroundBrush}" Foreground="{StaticResource PhoneForegroundBrush}"
                 Height="300" Width="250">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Visibility="Visible" x:Name="FavoriteListBoxTextBlock"  
                               FontSize="35" Foreground="Black" Text="{Binding AnswerName}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>

<StackPanel Grid.Row="0" Grid.Column= "0" HorizontalAlignment= "Left" VerticalAlignment= "Top" >
< Button x:Name= "FavoriteButton" FontFamily= "Segoe MDL2 Assets"
        Content= "&#xE006;" BorderBrush= "Transparent" FontSize= "28"
        Foreground= "{StaticResource PhoneForegroundBrush}"
        Style= "{StaticResource ButtonStyle1}" Click= "FavoriteButton_Click" />
</ StackPanel >

<StackPanel Grid.Row="0" Grid.Column= "2" HorizontalAlignment= "Left" VerticalAlignment= "Top" >
< Button x:Name= "FavoriteListButton" FontFamily= "Segoe MDL2 Assets"
        Content= "&#xEA55;" BorderBrush= "Transparent" FontSize= "28"
        Foreground= "{StaticResource PhoneForegroundBrush}"
        Style= "{StaticResource ButtonStyle1}" Click= "FavoriteListButton_Click" />
</StackPanel>

回答1:

In the MainPage constructor you have the sort code, but you don't set the content to the list box, which is why it didn't display in sorted order.

var sortedList = listobj.OrderBy(item => item.AnswerName).ToList();
this.FavoriteListBox.ItemsSource = sortedList; //you were using listobj, which isn't sorted

For the FavoriteButton_Click handler, you have a similar situation - you were sorting and saving the sorted results into a new list, which did not affect the original listobj instance. OrderBy is a LINQ extension which does not affect the original instance, so you can only clear and re-add the items to the original instance manually.

private void FavoriteButton_Click(object sender, RoutedEventArgs e)
{
    if (listobj.Any(l => l.AnswerName == AnswerTextBlock.Text))
        return;
    //add
    listobj.Add(new MyData { AnswerName = AnswerTextBlock.Text });
    //sort (does not modify the original listobj instance!)
    var sortedList = listobj.OrderBy(item => item.ToString()).ToList();

    //clear and re-add all items in the sorted order
    listobj.Clear();
    foreach( var item in sortedList )
    {
        listobj.Add( item );
    }

    using (IsolatedStorageFileStream fileStream = Settings1.OpenFile("MyStoreItems", FileMode.Create))
    {
        DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataList));
        serializer.WriteObject(fileStream, listobj);

    }
}

Also as a suggestion - you don't have to use MyDataList type, you can directly use ObservableCollection<MyData> everywhere.

Overall advice

As you can see this code is getting quite hard to maintain and keep functional. For that reason I suggest you to read some book on design patterns or Windows app development, especially to learn about MVVM pattern, data-binding and INotifyPropertyChanged. These are quite essential in building maintainable and stable Windows applications.

Also I think it would be helpful to learn some better C# code conventions - for better readability with more consistent variable naming (avoiding things like Settings1, listobj), commenting and code structure. It takes time but the end result is well worth the effort :-) .