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

时间:2014-01-22 21:30:30

标签: wpf visual-c++ c++-cx

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

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

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

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

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

1 个答案:

答案 0 :(得分:7)

如果没有更多背景信息,也没有关于您正在做什么的详细信息(因为您无法发布任何代码或屏幕截图),我只能告诉您The WPF Mentality背后的基本理念。

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

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

举个简单的例子,假设您有一个包含Personstring LastName属性的string FirstName类:

public class Person
{
    public string LastName {get;set;}
    public string FirstName {get;set;}
}

通过编写程序代码隐藏来代替将数据值来回传递给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;

您只需在XAML中定义 DataBinding ,声明性地说:

<TextBox Text="{Binding LastName}"/>
<TextBox Text="{Binding FirstName}"/>

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

//Window constructor example
public MainWindow()
{
    InitializeComponent();
    DataContext = new Person();
}

这种方法具有以下优点:

  • 显然Separates UI from Data,由于这些层的独立性,允许大量的可扩展性。您可以在UI中直接输入任何内容,而无需从应用程序逻辑/业务逻辑中更改单行代码。
  • 它减少了样板,因为WPF负责传递数据In Both DirectionsData <=> UI)。
  • 它允许基于属性的方法(而不是基于事件的方法)。例如,不需要处理TextBox.TextChanged事件。 WPF负责在需要时将示例中的TextBoxes的Text值传递给基础数据对象。
  • 无需导航Visual Tree 。 WPF Visual Tree是一个非常复杂的结构,它具有复杂的状态变化和复杂的转换以及复杂的生命周期。你真的想要处理它,比如说,“填充几个TextBoxes”
  • 在处理集合时,它有助于以自然的方式利用WPF的UI Virtualization功能(您实际上不必执行默认启用的任何操作)。这会导致Huge Performance Gain执行时间和内存消耗。
  • 最后但并非最不重要的是,它允许使用声明式方法,而不是传统的势在必行方法。您只需定义您的数据,然后编写业务逻辑(通常以命令形式),然后定义 UI及其与数据通过DataBinding的关系。

此基本概念适用于WPF中的一切

使用ListBox es,ComboBox es,Menu s,TabControl s,DataGrid s和所有ItemsControl s,这正是相同的:

您不要“使用UserControls填充ListBox”,而是:

  • 您创建了一个包含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...
        }
    }
    
  • 然后你定义 ListBox 在XAML中并使用WPF的Data Templating功能定义 UI的外观喜欢每个项目:

    <ListBox ItemsSource="{Binding People}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBox Text="{Binding LastName}"/>
                    <TextBox Text="{Binding FirstName}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox> 
    

    注意:如果您想在其中使用 UserControl ,则相同:

            <DataTemplate>
                <my:MyUserControl/>
            </DataTemplate>
    
  • 最后将UI的DataContext设置为ViewModel的一个实例:

    //Window Constructor
    public MainWindow()
    {
         InitializeComponent();
         DataContext = new MyViewModel();
    }
    
  

注意:我提到了INotifyPropertyChanged   评论中的界面。此界面必须才能实现   您的数据项或ViewModel以支持双向绑定   正常。否则WPF无法“知道”特定属性的时间   (例如LastName)已更改并相应地更新UI。一世   认为该主题超出了本答案的范围   因此,我不会进入它。您可以阅读链接的材料,和   网上还有很多关于它的资料。

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

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

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