【问题标题】:Self Sorting Listbox自排序列表框
【发布时间】:2011-04-14 11:27:37
【问题描述】:

完全被一些看似简单的事情难住了,已经被做死了……但仍然难住了。

我想做的事:我有一个 WinForms 列表框。它的项目由对象填充,DisplayMember 已设置。随着应用程序的运行,列出的项目中的数据可能会发生变化,包括 DisplayMember 后面的字段。我希望在发生这种情况时更改 ListBox 中显示的文本,并且我还希望 ListBox 自行重新排序,以便项目保持字母顺序。

当数据发生变化时,BindingList 可以很好地更新显示的文本,但对于我来说,我无法对其进行排序。

我查看了这个:http://msdn.microsoft.com/en-us/library/ms993236.aspx

这里有很多关于如何做到这一点的线程,但似乎都不适用于 ListBox。

在 ListBox 上设置 Sorted 属性同样没有帮助。

我需要做什么才能让 ListBox 自行排序?

【问题讨论】:

  • 您是直接绑定到 BindingList 还是使用 DataSource 然后使用 BindingList?后者我从来没有遇到过问题。
  • 我有一个对象列表(实际上是实体框架对象),我将它们传递给 BindingList 的构造函数,然后将该 BindingList 分配给 ListBox 的 DataSource。这将更新 DisplayMember,但不会自动排序。由于 BindingList 不是原生排序,这并不奇怪。但我似乎无法对其进行排序,即使我制作了自己的派生版本,如 MSDN 示例中那样,也无法通过其他方法。
  • 我们在这里讨论的是什么版本的 .Net?
  • 你考虑过自己实现 IBindingList 吗?
  • 我想知道您是否需要对 BindingList 中的项目使用 INotifyPropertyChanged 以便 ListBox 知道在 DisplayMember 属性更改后采取措施?虽然如果 ListBox 不能正确处理,我不会感到惊讶......

标签: c# winforms sorting listbox bindinglist


【解决方案1】:
namespace SilverlightApplication8
{
    public partial class MainPage : UserControl
    {
        ObservableCollection<UserData> users = new ObservableCollection<UserData>();
        public MainPage()
        {
            Service1Client client = new Service1Client();
            client.GetUsersCompleted += completed;
            client.GetUsersAsync(5);
            InitializeComponent();

            image.Source = new BitmapImage(new Uri(@"c:\1.JPG"));
        }    

        private void completed(object sender, GetUsersCompletedEventArgs e)
        {
            users=e.Result;

            UsersList.ItemsSource = users;
        }

        private void SelectionChngd(object sender, SelectionChangedEventArgs e)
        {
            UserData u= (UserData)(UsersList.SelectedItem);
            DescText.Text = u.Desc;

            image.Source = new BitmapImage(new Uri(@"http://profile.ak.fbcdn.net/hprofile-ak-snc4/49939_713180125_9000_q.jpg"));
        }

        private void Grid_MouseEnter(object sender, MouseEventArgs e)
        {
            if (UsersList.SelectedItem != null)
            {
                UserData u = (UserData)(UsersList.SelectedItem);
                DescText.Text = u.Desc;
            }
        }
    }
}

【讨论】:

  • -1 因为此代码与问题无关。如果我错了,请编辑您的答案并使其更清楚。
【解决方案2】:
<ListBox x:Name="UsersList"  SelectionChanged="SelectionChngd">
            <ListBox.ItemTemplate>
                <DataTemplate >
                    <Border BorderBrush="Red" BorderThickness="5">
                    <Grid MouseEnter="Grid_MouseEnter"> 
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                            <TextBlock   Text="{Binding Name}"/>
                        <TextBlock Grid.Row="1" Text="{Binding Email}"/>
                    </Grid>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>

        </ListBox>

【讨论】:

    【解决方案3】:

    我通过创建一个继承自 BindingList 的新类 BindingSortingList 来做到这一点。在其中,我覆盖了所有必要的方法,例如 ApplySortCore() 和 RemoveSortCore()。当您应用排序时,您基本上必须在内部将其复制到具有排序能力的标准列表中,对其进行排序,然后将其复制回“this”列表中。这似乎很疯狂,但现在我为此目的有一个可重用的类。

    【讨论】:

      【解决方案4】:

      列表控件上的 LVS_SORT 样式应该可以工作,但你说它不行。我会仔细检查它是否已应用。我从来没有遇到过自排序下拉列表控件的任何问题。请注意,这是我们所说的列表控件,而不是列表视图控件。

      【讨论】:

        【解决方案5】:

        重置数据源将有效地对列表框进行排序:

            listBox1.DataSource = null;
            listBox1.DataSource = myBindingList;
            listBox1.DisplayMember = "MyField";
        

        但这不是自动的。据我了解,只要通过事件或类似的方式更新 DisplayMember 后面的字段,就应该进行排序......

        无论如何,请查看我的完整测试:

        public partial class Form1 : Form
        {
            public BindingList<ABC> myBindingList = new BindingList<ABC>();
        
            public Form1() {
                InitializeComponent();
            }
        
            private void button1_Click(object sender, EventArgs e) {
                myBindingList.Add(new ABC("zzz"));
                myBindingList.Add(new ABC("aaa"));
            }
        
            private void button2_Click(object sender, EventArgs e) {
                myBindingList[0].MyField = "ccc"; // was "zzz"
                myBindingList[1].MyField = "ddd"; // was "aaa"
        
                listBox1.DataSource = null;
                listBox1.DataSource = myBindingList;
                listBox1.DisplayMember = "MyField";
            }
        
            private void Form1_Load(object sender, EventArgs e) {
                listBox1.DataSource = myBindingList;
                listBox1.DisplayMember = "MyField";
        
            }
        }
        
        public class ABC  {
            public string MyField { get; set; } 
            public ABC(string val) {
                MyField = val;
            }
        }
        

        【讨论】:

          【解决方案6】:

          与 Patrol02 的帖子一样,但是您可能希望尝试将 DataSource 设置为 null,然后根据列表大小更改触发的事件重新分配它。您可以在集合上使用观察者模式,覆盖 Add 和 Remove 方法来通知观察者重新绑定自己。

          【讨论】:

          • 一个可行的选择是使用一个 BindingList,它有一个 ListChanged 的​​事件,连接到该事件,检测更改,并使用它作为重新填充 ListBox 的提示。我发现绑定到 DataSource 在这里效果不佳,而是必须清除并重新填充 ListBox 中的项目。这有点不雅,我希望有更好的解决方案......但它确实有效。
          【解决方案7】:

          您可以使用 BindingSource 对象。 只需将其拖放到您的表单中并将您的 ListBox.DataSource 属性指向此 BindingSource 对象。 然后转到 BindingSource 的属性并根据需要定义 Sort。

          然后您可以在代码中设置myBindingSource.DataSource = myCollection,瞧,您的列表框已填充并排序。 很简单。

          【讨论】:

          • BindingSource 在更改后似乎没有重新排序。它最终的行为与 BindingList 非常相似。它显示 DisplayMember 的重命名,但不对项目进行排序。我尝试将 SortableBindingList 作为它的 DataSource,它显示为 SupportsSorting,但是当事情发生变化时,仍然没有排序。
          【解决方案8】:
           private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
              {
                //Sorting function
              }
          

          这个呢??

          【讨论】:

          • ListBox 后面的数据实际上会随着所选项目的变化而变化。用户将选择该项目,该项目将使用该项目的信息填充一个表单,允许他们更改它。这样做时,他们可能会更改 Listbox 上 DisplayMember 后面的属性。那是我希望它重新排序的时候,这实际上是他们在另一个表单上点击保存的时候。我尝试连接到 ListBox 后面的 BindingList 的 ListChanged 事件,在那里排序,看到 BindingList 排序,但是 ListBox 没有重绘本身,它只会更新更改的项目。
          猜你喜欢
          • 2011-03-02
          • 2014-02-14
          • 2011-09-30
          • 2012-05-01
          • 2015-07-11
          • 1970-01-01
          • 2023-01-31
          • 2022-09-28
          • 2017-11-06
          相关资源
          最近更新 更多