使用 MVVM 代码绑定对 ListBox 进行排序

发布于 2024-12-07 15:48:06 字数 1545 浏览 0 评论 0原文

我有一个 ListBox,它可以使用代码隐藏 MVVM 对象来显示数据。但是,我想对条目进行排序,因此我认为中间的 CollectionViewSource 可能会起作用。但相反,程序在启动时崩溃。

原始xaml提取:

<ListBox SelectedItem="{Binding SelectedCategory}"
    DisplayMemberPath="name"
    ItemsSource="{Binding Categories}"
    Name="CategoriesListBox" />

提取后面的代码:

public class ViewModel : INotifyPropertyChanged
    {
        private trainCategory[] _categories;
        private trainCategory _selectedCategory;

        public event PropertyChangedEventHandler PropertyChanged;

        public trainCategory[] Categories
        {
            get { return _categories; }
            set
            {
                if (_categories == value)
                {
                    return;
                }
                _categories = value;
                RaisePropertyChanged("Categories");
            }
        } //etc

ListBox的替换XAML:

<ListBox SelectedItem="{Binding SelectedCategory}"
    DisplayMemberPath="name"
    ItemsSource="{Binding Source={StaticResource SortedItems}}"
    Name="CategoriesListBox" />

和CollectionViewSource:

<CollectionViewSource x:Key="SortedItems" Source="{Binding Categories}">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="name"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

在我看来,CollectionViewSource位于视图模型和ListBox之间,但它显然没有(或者我做错了)。任何指示表示赞赏。

I have a ListBox which happily displays data using a code-behind MVVM object. However, I want to sort the entries and so I thought an intermediate CollectionViewSource might work. But instead the program crashes on startup.

Original xaml extract:

<ListBox SelectedItem="{Binding SelectedCategory}"
    DisplayMemberPath="name"
    ItemsSource="{Binding Categories}"
    Name="CategoriesListBox" />

Code behind extract:

public class ViewModel : INotifyPropertyChanged
    {
        private trainCategory[] _categories;
        private trainCategory _selectedCategory;

        public event PropertyChangedEventHandler PropertyChanged;

        public trainCategory[] Categories
        {
            get { return _categories; }
            set
            {
                if (_categories == value)
                {
                    return;
                }
                _categories = value;
                RaisePropertyChanged("Categories");
            }
        } //etc

Replacement XAML for ListBox:

<ListBox SelectedItem="{Binding SelectedCategory}"
    DisplayMemberPath="name"
    ItemsSource="{Binding Source={StaticResource SortedItems}}"
    Name="CategoriesListBox" />

And the CollectionViewSource:

<CollectionViewSource x:Key="SortedItems" Source="{Binding Categories}">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="name"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

It seems to me that the CollectionViewSource goes in between the view model and the ListBox, but it clearly doesn't (or I've done it wrong). Any pointers appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月棠 2024-12-14 15:48:06

使用原始 xaml

<ListBox SelectedItem="{Binding SelectedCategory}" 
    DisplayMemberPath="name" 
    ItemsSource="{Binding Categories}" 
    Name="CategoriesListBox" /> 

更新视图模型以使用列表:

   public List<trainCategory> _categories;
   public List<trainCategory> Categories 
    { 
        get 
        {   // This LINQ statement returns a sorted list
            return (from c in _categories
                    orderby c
                    select c);
        } 
        set 
        { 
            if (_categories == value) 
            { 
                return; 
            } 
            _categories = value; 
            RaisePropertyChanged("Categories"); 
        } 
    } //etc 

然后您可以跳过尝试绑定到静态资源的所有麻烦。只需将 strait 绑定到视图模型中的属性即可。

或者,您仍然可以在视图模型中使用数组作为支持变量:

   public trainCategory[] _categories;
   public List<trainCategory> Categories 
    { 
        get 
        {   // This LINQ statement returns a sorted list
            return (from c in _categories
                    orderby c
                    select c).ToList();
        } 
        set 
        { 
            if (_categories == value.ToArray()) 
            { 
                return; 
            } 
            _categories = value.ToArray();
            RaisePropertyChanged("Categories");
        } 
    } //etc 

Use your original xaml

<ListBox SelectedItem="{Binding SelectedCategory}" 
    DisplayMemberPath="name" 
    ItemsSource="{Binding Categories}" 
    Name="CategoriesListBox" /> 

Update your View Model to use a List instead:

   public List<trainCategory> _categories;
   public List<trainCategory> Categories 
    { 
        get 
        {   // This LINQ statement returns a sorted list
            return (from c in _categories
                    orderby c
                    select c);
        } 
        set 
        { 
            if (_categories == value) 
            { 
                return; 
            } 
            _categories = value; 
            RaisePropertyChanged("Categories"); 
        } 
    } //etc 

Then you can skip all that nastiness of trying to bind to a static resporce. Just bind strait to the property in your view model.

Alternately, you can still use arrays as your backing variable in your viewmodel:

   public trainCategory[] _categories;
   public List<trainCategory> Categories 
    { 
        get 
        {   // This LINQ statement returns a sorted list
            return (from c in _categories
                    orderby c
                    select c).ToList();
        } 
        set 
        { 
            if (_categories == value.ToArray()) 
            { 
                return; 
            } 
            _categories = value.ToArray();
            RaisePropertyChanged("Categories");
        } 
    } //etc 
德意的啸 2024-12-14 15:48:06

启动时遇到什么异常?请记住将 Resources 部分放在需要使用资源的所有其他代码之前。

另一种替代方法是:

<ListBox SelectedItem="{Binding SelectedCategory}" DisplayMemberPath="name" Name="CategoriesListBox">
    <ListBox.ItemsSource>
        <Binding>
            <Binding.Source>
                <CollectionViewSource Source="{Binding Categories}">
                    <CollectionViewSource.SortDescriptions>
                        <scm:SortDescription PropertyName="name"/>
                    </CollectionViewSource.SortDescriptions>
                </CollectionViewSource>
            </Binding.Source>
        </Binding>
    </ListBox.ItemsSource>
</ListBox>

在任何情况下,还请记住为 scm 提供正确的 xmlns 声明。

What exception are you getting on startup? Remember to have your Resources section before all other code that needs to use the resources.

An alternative to that would be:

<ListBox SelectedItem="{Binding SelectedCategory}" DisplayMemberPath="name" Name="CategoriesListBox">
    <ListBox.ItemsSource>
        <Binding>
            <Binding.Source>
                <CollectionViewSource Source="{Binding Categories}">
                    <CollectionViewSource.SortDescriptions>
                        <scm:SortDescription PropertyName="name"/>
                    </CollectionViewSource.SortDescriptions>
                </CollectionViewSource>
            </Binding.Source>
        </Binding>
    </ListBox.ItemsSource>
</ListBox>

Also remember to have the proper xmlns declaration for scm in any case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文