何时将数据加载到ListBox中的最佳实践

use*_*339 0 wpf visual-c++ c++-cx

WPF/VC++(C++/cx) - Visual Studio 2013

所以我有一个ListBox,其中填充了我创建的UserControl.每次页面更改时数据都会丢失,这是不幸的.因此,我可以选择在每次加载页面时将数据加载到ListBox中,或者在页面之间传递数据.他们每个人都有自己的优势和劣势,但有一种做法更受欢迎吗?

我想要考虑的事情是ListBox中有多少UserControl,这可能是一个很大的数量(大到10000+),以及数据的存储方式.现在我将数据存储在AVLTree中,主要用于组织,因此不需要进行排序.通常只有10页,其中6页通常被导航到(其中4页是很少使用或仅使用过一次的菜单页面),因此数据不必经常在页面之间传递.每个数据节点的大小只有大约1mb,所以不是很大,但是大到足以在你开始超过10000个条目时产生差异(这可能被认为是一种罕见的情况).

我来自游戏编程,因此速度和效率是首要目标.

是的,这是一个主观问题,但是专业人士或一般编程社区可能有一个首选方法.

Fed*_*gui 7

没有任何更多的背景信息,也没有关于你正在做什么的详细信息(因为你不能发布任何代码或截图),我只能告诉你WPF心态背后的基本理念是什么.

WPF与我听说过的任何其他UI框架都有很大不同,因为它实际上是用于以数据为中心的开发.

从头开始,WPF主要基于DataBinding.这样就消除了95%的需要通过程序代码对UI进行任何操作.

举个简单的例子,假设你有一个Person包含string LastNamestring FirstName属性的类:

public class Person
{
    public string LastName {get;set;}
    public string FirstName {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

而不是通过编写程序代码隐藏来向UI传递数据值,如下所示:

//Traditional approach, Don't use this in WPF.
this.txtLastName.Text = person.LastName;
this.txtFirstName.Text = person.FirstName;
//...
person.LastName = this.txtLastName.Text;
person.FirstName = this.txtFirstName.Text;
Run Code Online (Sandbox Code Playgroud)

您只需以声明方式在XAML中定义DataBinding:

<TextBox Text="{Binding LastName}"/>
<TextBox Text="{Binding FirstName}"/>
Run Code Online (Sandbox Code Playgroud)

然后将UI的DataContext设置为相关的数据实例:

//Window constructor example
public MainWindow()
{
    InitializeComponent();
    DataContext = new Person();
}
Run Code Online (Sandbox Code Playgroud)

这种方法具有以下优点:

  • 它清楚地将UI与数据分离,由于这些层的独立性,允许大量的可扩展性.您可以在UI中直接输入任何内容,而无需从应用程序逻辑/业务逻辑中更改单行代码.
  • 它减少了样板,因为WPF负责在两个方向(Data <=> UI)中传递数据.
  • 它允许基于属性的方法(而不是基于事件的方法).例如,不需要处理TextBox.TextChanged事件.WPF负责Text在需要时将示例中的TextBoxes 的值传递给基础Data Object.
  • 它消除了导航Visual Tree的需要.WPF Visual Tree是一个非常复杂的结构,具有复杂的状态变化和复杂的转换以及复杂的生命周期.你真的希望有才能,比方说,处理这种"填充了几个文本框".
  • 在处理集合时,它有助于以自然的方式利用WPF的UI虚拟化功能(您实际上不必执行默认启用的任何操作).这导致巨大的性能在执行时间和内存消耗方面都获得了收益.
  • 最后但并非最不重要的是,它允许采用声明式方法,而不是传统的命令式方法.您只需定义数据,然后编写业务逻辑(通常以命令形式),然后通过DataBinding 定义 UI及其与数据的关系.

这个基本概念适用于一切在WPF.

使用ListBoxes,ComboBoxes,Menus,TabControls,DataGrids和ALL ItemsControls它们完全相同:

您没有"使用UserControls填充ListBox",而是:

  • 您创建一个适当的ViewModel,其中包含一个IEnumerable<T>包含数据项的ViewModel.这ObservableCollection<T>是首选,因为WPF会监听它的CollectionChanged事件,并在从集合中添加/删除项目时相应地更新UI:

    public class MyViewModel
    {
        public ObservableCollection<Person> People {get;set;}
    
        //Constructor
        public MyViewModel()
        {
           People = new ObservableCollection<Person>();
    
           //populate the collection here...
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 然后在XAML中定义 ListBox 并使用WPF的数据模板功能来定义 UI对每个项目的外观:

    <ListBox ItemsSource="{Binding People}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBox Text="{Binding LastName}"/>
                    <TextBox Text="{Binding FirstName}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox> 
    
    Run Code Online (Sandbox Code Playgroud)

    注意:如果你想 在那里使用a ,它也是一样的UserControl :

            <DataTemplate>
                <my:MyUserControl/>
            </DataTemplate>
    
    Run Code Online (Sandbox Code Playgroud)
  • 最后将UI的DataContext设置为ViewModel的一个实例:

    //Window Constructor
    public MainWindow()
    {
         InitializeComponent();
         DataContext = new MyViewModel();
    }
    
    Run Code Online (Sandbox Code Playgroud)

注意:INotifyPropertyChanged 在评论中提到了界面.此接口必须由您的数据项或ViewModel实现,以便正确支持双向绑定.否则,WPF无法"知道"何时LastName更改特定属性(例如)并相应地更新UI.我认为这个话题超出了这个答案的范围,因此我不会深入研究.您可以阅读链接的材料,网上也有大量有关它的资料.

正如我已经提到的,我在C++中根本没有经验,因此所有这些例子都在C#中.记得我还提到WPF只支持对.Net对象的数据绑定,我认为它不支持低层内存结构,例如你可以用C++构建的结构.

我的建议是,您将C#用于软件的高级UI部分,同时将C++用于您可能需要的任何低级操作.

我强烈建议阅读本文中链接的材料,最重要的是Rachel的WPF Mentality和ItemsControl相关材料.