• 数据库组合框失败和更多


    介绍 本文将逐步深入 研究一个常用的。net构造(数据绑定)。首先,本文设置一个简单的程序,该程序使用DisplayMember和ValueMember属性将一组对象绑定到一个ComboBox。其次,它说明了这种做法经常会失败。在那之后,我们将看到解决问题的方法,并了解为什么在控件中,在Visual Studio中,在某些地方可能会有错误。 背景 我在很长一段时间以前发现了这个问题,但一直无法确定为什么会出现这个问题,因为这是一个更大的程序的一部分。所以,我决定写一个具体的程序和文章,提供具体的细节。 如何将对象的值直接绑定到组合框。发生什么问题、错误和失败。为什么这些问题经常发生。 使用的代码 在阅读本文时,您将看到代码经过了许多细微的修改,以向您展示在此过程中会发生什么。附加的代码实现了数组,ToString()覆盖了Animal类。读完这篇文章,你就会明白了。 最后的代码是一个基本的Windows窗体项目与一个额外的类,保持非常简单的努力,以创建一个清楚的例子,正在发生: 下面是动物类: 隐藏,收缩,复制Code

    class Animal
    {
        private string commonName;
        private string species;
        private int speciesId;
        // Creates a class (global) randomizer used
        // to generate a unique id for each species
        static Random rnd = new Random();
    
        public Animal(string inSpecies, string inCommonName)
        {
            // original code
            this.speciesId = rnd.Next();
            species = inSpecies;
            commonName = inCommonName;
        }
    
        public int SpeciesId
        {
            get
            {
                return speciesId;
            }
        }
        public string Species
        {
            get
            {
                return species;
            }
        }
        public string CommonName
        {
            get
            {
                return commonName;
            }
        }
    }

    头足类动物的细节 通过使用Animal类,可以很容易地将动物列表绑定到ComboBox。在有ComboBox的表单代码中,我们将创建一个动物数组,然后将它们绑定到ComboBox。它看起来如下: 隐藏,复制Code

    public partial class Form1 : Form
    {
        // set up an array to hold some animals
        Animal[] allAnimals = new Animal[10];
        public Form1()
        {
            InitializeComponent();
            // initialize some animals
            InitAnimals();
    
            
            comboBox1.DisplayMember = "CommonName";
            comboBox1.ValueMember = "SpeciesId";
            comboBox1.DataSource = allAnimals;
        }
    
        private void InitAnimals()
        {
            //create 3 animals and add them to the array.
            allAnimals[0] = new Animal("Fidelis Caninus", "Dog");
            allAnimals[1] = new Animal("Felinus Catticus", "Cat");
            allAnimals[2] = new Animal("Elephantos Largus", "Elephant");
    
        }
    }

    这段代码将生成一个将动物对象绑定到ComboBox的应用程序,如下所示: 第二个图像:显示一个空项目 还请注意,第二幅图像显示的是程序第一次启动时的样子。好的方面是这个组合框有一个空项目。换句话说,用户还没有选择一个选项。这可能看起来还不重要,但当我们试图解决下面的问题时,它会很重要。所以,现在,只要记住它。 现在,让我们添加一个事件处理程序,以便选择其中一项来做一些事情。在Visual Studio中,确保选择了ComboBox,然后切换到窗体的属性对话框中的事件视图,并添加selectedindexchangeevent。你会得到一个方法,看起来像: 隐藏,复制Code

    private void comboBox1_SelectedIndexChanged_1(object sender, EventArgs e)
    {
        Animal currentAnimal = (Animal)comboBox1.SelectedItem;
        MessageBox.Show(this,currentAnimal.Species);
    }

    当运行程序并在组合框中选择一个项目时,事件处理程序将触发,获取当前选中的项目,将其强制转换为一个动物对象,并显示该动物的物种名称。它看起来如下所示,取决于您选择的项目: 我们为什么要Cast这个项目? 我们对从ComboBox返回的项进行了强制转换,因为我们告诉它将该项存储在ComboBox的列表中,但ComboBox只是将其存储为一个对象——所有对象的母对象。因为我们从特定的(动物)对象中有特定的属性,所以我们将它转换为它的真实类型。 看起来很好 所以,你可能会注意到它似乎工作得很好。但是你们有些人可能已经注意到了一个问题。问题:有一个数组有一些空元素。我将数组的大小定义为10,但我只newed了三个动物对象。 工作:除非你改变订单 好了,你看到代码真的能工作,那么这有关系吗?现在,我们假设这无关紧要。但是,让我们更改一行代码,并显示它将导致代码中断。 隐藏,复制Code

    public Form1()
    {
        InitializeComponent();
        
        //My private method to create some animals
        InitAnimals();
    
        comboBox1.DataSource = allAnimals;
        // set the Animal property which will be used as the DisplayMember
        comboBox1.DisplayMember = "CommonName";
        // set the Animal property which will be used as the ValueMember
        comboBox1.ValueMember = "SpeciesId";
    }

    飞机失事 注意,我所做的惟一更改是移动了设置DataSource的那一行:comboBox1。数据源=动物;。在前面,我在设置DisplayMember和ValueMember之后设置了它。现在,我把它放在前面。现在,当您尝试运行程序时,它会立即崩溃。您将看到如下内容: 为什么会崩溃? 为了找出程序崩溃的原因,我使用调试器逐步分析了代码。抛出以下异常: 但是,这没有多大意义。为什么它告诉我值不能为空?我的值不是空的。它是一个非常好的字符串,它指向我的Animal类的ValueMember SpeciesId。另外,如果我把这条线放晚一点,它就行了。 关于数据绑定的微软文档? 也许微软甚至声称你必须按照这个顺序来做?事实上,他们不喜欢。就文档而言,我所创建的应该是好的。但是,它不是。 1解决方案解决方案 第一个也是最明显的解决方案是:不要这样做。换句话说,只需最后设置数据源成员,然后忘记它。但这听起来像是一个完全神奇的解决方案,所以让我们寻找另一个。 第二个解决方案:处理(丢弃)异常 好吧,我们把这个异常扔掉。我只是简单地把线绕起来试试……它处理ArgumentNullException。它看起来是这样的: 隐藏,复制Code

    try
    {
        comboBox1.ValueMember = "SpeciesId";
    }
    catch (ArgumentNullException ex)
    {
    
    }

    并尝试…Catch…工作吗? 它的工作。应用程序是星形的,一切看起来都很好,直到我点击组合框。请看下面两张图片: 奇怪的显示值 发生了什么事?为什么我现在有这些奇数的显示值?这些奇怪的显示值从何而来? 仔细看看动物类 嘿,还记得我在Animal类中生成的ID吗?我这样做是为了模拟一个可能从数据库或类似的地方得到的值。这样做的代码是这样的: 隐藏,复制Code

    public Animal(string inSpecies, string inCommonName)
    {
        this.speciesId = rnd.Next();
        species = inSpecies;
        commonName = inCommonName;
    }

    我做了更多的分析并确定,是的,这就是这些值的来源。但为什么它们被设置为DisplayValue呢?如果我选择其中一个值会发生什么?这个程序如你(可能)所期望的那样工作。它是这样的: 第三个解决方案解决方案 好吧,我们试试别的怎么样?我们甚至不要设置愚蠢(是的,我说了愚蠢)comboBox1.ValueMember。我们忽略它。让我们把这行代码注释掉,然后再试一次。以下是代码和结果: 隐藏,复制Code

    //comboBox1.ValueMember = "SpeciesId";

    同样,一开始一切看起来都很好。然后我把名单放下,然后…什么?现在,它列出了我的名称空间。类名作为显示成员。疯了!但是,它仍然有效,如果你能称之为有效的话。 A Clue and ToString() 至少这给了我一个线索。现在,我想,嘿,这使用的是动物类ToString()方法的默认值。让我们重写ToString()方法,看看我能做什么。因此,我进入Animal类并添加以下重载方法。注意,自动机器人编码器(Visual Studio Helper)尝试添加返回值base.ToString();行代码,但注释掉了。我不想做默认行为。 相反,我告诉它返回我的Animal类的commonName属性。 隐藏,复制Code

    public override string ToString()
    {
        return this.commonName;
        //return base.ToString();
    }

    它是有效的,但是等等!应该吗? 这是它现在的样子,当我运行它的时候。 所以它起作用了,但我不认为它应该起作用。微软告诉你,你需要设置这三个项目: comboBox1。DisplayMember = " CommonName "; comboBox1。ValueMember = " SpeciesId "; comboBox1。数据源=动物; 但是,记住,现在我只设置DisplayMember。我甚至没有设置ValueMember,因为我把它注释掉了。为什么我不再需要了?控件如何区分正确的项/值? 这是另一个解决方案 丢失数组,使用列表(集合) 也许这都和使用这个数组有关,这个数组中有些元素仍然是空的?我要修改代码,让它使用一个集合。这是代码: 隐藏,复制Code

    // set up a collection to hold some animals
    List<animal> allAnimals = new List<animal>();
    public Form1()
    {
        InitializeComponent();
        
        //My private method to create some animals
        InitAnimals();
        // Please note that in this example,
        // the DataSource is set first.
        // However, with a list it will work.
        comboBox1.DataSource = allAnimals;    
        // set the Animal property which will be used as the DisplayMember
        comboBox1.DisplayMember = "CommonName";
        // set the Animal property which will be used as the ValueMember
        comboBox1.ValueMember = "SpeciesId";
    
    }
    
    private void InitAnimals()
    {
        //create 3 animals and add them to the array.
        allAnimals.Add(new Animal("Fidelis Caninus", "Dog"));
        allAnimals.Add(new Animal("Felinus Catticus", "Cat"));
        allAnimals.Add(new Animal("Elephantos Largus", "Elephant"));
    }

    我还通过删除先前添加的ToString()修改了Animal类。 现在我运行它,我看到的第一件事是 是的,在我看到主要形式之前我就看到了。显然,现在combobox的SelectedItemChanged事件在我启动程序后立即运行。为什么?还有什么地方可以解释这一点?任何地方?有人知道吗? 在此之后,将出现主表单,看起来如下所示: 组合框空白项:它不见了! 还记得我让你们注意组合框里有一个空白条目吗?我做到了。在本文的顶部,我说,“嘿,看,combobox中有一个空白项,因为用户还没有选择。”好吧,我已经让你注意到了,所以我们现在就开始谈论它。你看,它现在不见了。 嘿,你可能认为这没什么大不了的。我们可以避开它。我知道,但为什么没有任何东西与整个捆绑一致呢?这不是很容易吗? 希望能帮助 我希望能帮助那些在不同地方遇到这个问题的人。 历史 02.04.2010—发布了本文和代码的第一版。 本文转载于:http://www.diyabc.com/frontweb/news380.html

  • 相关阅读:
    HDU 1713 相遇周期 (最小公倍数)
    HDU 1270 小希的数表 (暴力枚举+数学)
    HDU 1052 Tian Ji -- The Horse Racing (贪心)
    CodeForces 732D Exams (二分)
    CodeForces 732C Sanatorium (if-else)
    CodeForces 732B Cormen — The Best Friend Of a Man (贪心)
    CodeForces 732A Buy a Shovel (水题)
    CodeForces 743C Vladik and fractions (数论)
    Node基础
    正向代理与反向代理
  • 原文地址:https://www.cnblogs.com/Dincat/p/13443949.html
Copyright © 2020-2023  润新知