Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何使列表框刷新其项目文本?_.net_Winforms_User Interface - Fatal编程技术网

.net 如何使列表框刷新其项目文本?

.net 如何使列表框刷新其项目文本?,.net,winforms,user-interface,.net,Winforms,User Interface,我正在为一个还没有意识到像ListBox这样的控件不必包含字符串的人做一个例子;他一直在存储格式化字符串,并跳过复杂的解析环,以便从列表框中获取数据,我想向他展示一种更好的方法 我注意到,如果我在列表框中存储了一个对象,然后更新一个影响到字符串的值,列表框不会自动更新。我尝试在控件上调用Refresh和Update,但两者都不起作用。下面是我正在使用的示例的代码,它要求您将列表框和按钮拖到表单上: Public Class Form1 Protected Overrides Sub O

我正在为一个还没有意识到像
ListBox
这样的控件不必包含字符串的人做一个例子;他一直在存储格式化字符串,并跳过复杂的解析环,以便从
列表框中获取数据,我想向他展示一种更好的方法

我注意到,如果我在
列表框
中存储了一个对象,然后更新一个影响
到字符串
的值,
列表框
不会自动更新。我尝试在控件上调用
Refresh
Update
,但两者都不起作用。下面是我正在使用的示例的代码,它要求您将列表框和按钮拖到表单上:

Public Class Form1

    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        MyBase.OnLoad(e)

        For i As Integer = 1 To 3
            Dim tempInfo As New NumberInfo()
            tempInfo.Count = i
            tempInfo.Number = i * 100
            ListBox1.Items.Add(tempInfo)
        Next
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        For Each objItem As Object In ListBox1.Items
            Dim info As NumberInfo = DirectCast(objItem, NumberInfo)
            info.Count += 1
        Next
    End Sub
End Class

Public Class NumberInfo

    Public Count As Integer
    Public Number As Integer

    Public Overrides Function ToString() As String
        Return String.Format("{0}, {1}", Count, Number)
    End Function
End Class
我认为问题可能在于使用字段并尝试实现INotifyPropertyChanged,但这没有效果。(我之所以使用字段,是因为这是一个示例,我不想添加几十行与我演示的主题无关的内容。)

老实说,我从来没有尝试过像这样更新项目;在过去,我总是添加/删除项目,而不是编辑它们。所以我从来没有注意到我不知道如何让它工作


那么我缺少什么呢?

在列表框的datasource和datasource属性之间使用datasource属性和BindingSource对象。那就刷新一下

更新添加了示例

像这样:

Public Class Form1

    Private datasource As New List(Of NumberInfo)
    Private bindingSource As New BindingSource

    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        MyBase.OnLoad(e)

        For i As Integer = 1 To 3
            Dim tempInfo As New NumberInfo()
            tempInfo.Count = i
            tempInfo.Number = i * 100
            datasource.Add(tempInfo)
        Next
        bindingSource.DataSource = datasource
        ListBox1.DataSource = bindingSource
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        For Each objItem As Object In datasource
            Dim info As NumberInfo = DirectCast(objItem, NumberInfo)
            info.Count += 1
        Next
        bindingSource.ResetBindings(False)
    End Sub
End Class

Public Class NumberInfo

    Public Count As Integer
    Public Number As Integer

    Public Overrides Function ToString() As String
        Return String.Format("{0}, {1}", Count, Number)
    End Function
End Class

我对vb.net不太了解,但在C中,您应该使用datasource,然后通过调用
listbox对其进行绑定。bind()
可以做到这一点。

如果您从listbox派生,则可以调用受RefreshItem保护的方法。只需在您自己的类型中重新公开此方法

public class ListBox2 : ListBox {
    public void RefreshItem2(int index) {
        RefreshItem(index);
    }
}

然后将设计器文件更改为使用自己的类型(在本例中为ListBox2)。

当需要更新列表框时,我使用此类

根据索引是否可用,更新列表中的对象,然后调用其中一个包含的方法。如果要更新列表中包含的对象,但没有索引,则必须调用RefreshItems并更新所有项目

public class RefreshingListBox : ListBox
{
    public new void RefreshItem(int index)
    {
        base.RefreshItem(index);
    }

    public new void RefreshItems()
    {
        base.RefreshItems();
    }
}

这有点不专业,但很有效。 我刚刚删除并添加了该项目(也再次选择了它)。 该列表是根据“显示和更改”属性排序的,因此,对我来说也没问题。副作用是引发额外的事件(索引已更改)

if (objLstTypes.SelectedItem != null)
{
 PublisherTypeDescriptor objType = (PublisherTypeDescriptor)objLstTypes.SelectedItem;
 objLstTypes.Items.Remove(objType);
 objLstTypes.Items.Add(objType);
 objLstTypes.SelectedItem = objType;
}

如果objLstTypes是您的列表框名称 使用 objLstTypes.Items.Refresh();
希望这能起作用…

BindingList自行处理绑定的更新

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace TestBindingList
{
    public class Employee
    {
        public string Name { get; set; }
        public int Id { get; set; }
    }

    public partial class Form1 : Form
    {
        private BindingList<Employee> _employees;

        private ListBox lstEmployees;
        private TextBox txtId;
        private TextBox txtName;
        private Button btnRemove;

        public Form1()
        {
            InitializeComponent();

            FlowLayoutPanel layout = new FlowLayoutPanel();
            layout.Dock = DockStyle.Fill;
            Controls.Add(layout);

            lstEmployees = new ListBox();
            layout.Controls.Add(lstEmployees);

            txtId = new TextBox();
            layout.Controls.Add(txtId);

            txtName = new TextBox();
            layout.Controls.Add(txtName);

            btnRemove = new Button();
            btnRemove.Click += btnRemove_Click;
            btnRemove.Text = "Remove";
            layout.Controls.Add(btnRemove);

            Load+=new EventHandler(Form1_Load);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _employees = new BindingList<Employee>();
            for (int i = 0; i < 10; i++)
            {
                _employees.Add(new Employee() { Id = i, Name = "Employee " + i.ToString() }); 
            }

            lstEmployees.DisplayMember = "Name";
            lstEmployees.DataSource = _employees;

            txtId.DataBindings.Add("Text", _employees, "Id");
            txtName.DataBindings.Add("Text", _employees, "Name");
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            Employee selectedEmployee = (Employee)lstEmployees.SelectedItem;
            if (selectedEmployee != null)
            {
                _employees.Remove(selectedEmployee);
            }
        }
    }
}
使用系统;
使用系统组件模型;
使用System.Windows.Forms;
命名空间TestBindingList
{
公营雇员
{
公共字符串名称{get;set;}
公共int Id{get;set;}
}
公共部分类Form1:Form
{
私有绑定列表\u员工;
私营企业员工;
私有文本框txtId;
私有文本框txtName;
私人按钮btnRemove;
公共表格1()
{
初始化组件();
FlowLayoutPanel布局=新的FlowLayoutPanel();
layout.Dock=DockStyle.Fill;
控件。添加(布局);
lstmemployees=newlistbox();
布局.控件.添加(LST);
txtId=新文本框();
layout.Controls.Add(txtId);
txtName=newtextbox();
layout.Controls.Add(txtName);
btnRemove=新建按钮();
btnRemove.Click+=btnRemove\u Click;
btnRemove.Text=“删除”;
布局.Controls.Add(btnRemove);
Load+=新事件处理程序(Form1_Load);
}
私有void Form1\u加载(对象发送方、事件参数e)
{
_employees=newbindingslist();
对于(int i=0;i<10;i++)
{
_Add(newemployee(){Id=i,Name=“Employee”+i.ToString()});
}
lstmemployees.DisplayMember=“Name”;
lstEmployees.DataSource=\u employees;
添加(“文本”,雇员,“Id”);
txtName.DataBindings.Add(“Text”,_employees,“Name”);
}
私有void btnRemove_单击(对象发送者,事件参数e)
{
Employee selectedEmployee=(Employee)lstEmployees.SelectedItem;
如果(selectedEmployee!=null)
{
_员工。删除(选定员工);
}
}
}
}

如果使用以下绘制方法:

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    e.DrawFocusRectangle();

    Sensor toBeDrawn = (listBox1.Items[e.Index] as Sensor);
    e.Graphics.FillRectangle(new SolidBrush(toBeDrawn.ItemColor), e.Bounds);
    e.Graphics.DrawString(toBeDrawn.sensorName, new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold), new SolidBrush(Color.White),e.Bounds);
}
传感器是我的班级

因此,如果我在某处更改类
颜色
,您只需将其更新为:

int temp = listBoxName.SelectedIndex;
listBoxName.SelectedIndex = -1;
listBoxName.SelectedIndex = temp;

而且
颜色将更新,这只是另一个解决方案:)

这是用于互联网的。我想这个人对WinForm感兴趣。太好了。出于某种原因,无论我在WPF中使用了多少WinForms中的数据绑定,WinForms中的数据绑定作为一种解决方案都不会突然出现在我面前。类似于:((CurrencyManager)this.BindingContext[ListBox1]).Refresh();从BindingContext中获取“隐藏”对象,然后将其强制转换为货币管理器。虽然这是C#,因为我在VB.NET中从未这样做过。这是一个很好的答案,但最终geno建议使用BindingList会减少工作量。实际上,这比目前公认的答案工作量要少。壮丽的我编辑了你的文章,加入了一个例子。我认为你可以进一步改进。您可以将父绑定和子绑定应用于控件,这意味着您可以不使用_SelectedIndexChanged事件处理程序。但我忘记了确切的代码….:(我更新了示例,删除了SelectedIndexChanged事件处理程序,并在加载处理程序中替换为两行新行。:)我使用的是一个常规列表,但我认为这不是问题所在,并在其他地方查找问题。谢谢据我所知,这并不能解决这个问题
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    e.DrawFocusRectangle();

    Sensor toBeDrawn = (listBox1.Items[e.Index] as Sensor);
    e.Graphics.FillRectangle(new SolidBrush(toBeDrawn.ItemColor), e.Bounds);
    e.Graphics.DrawString(toBeDrawn.sensorName, new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold), new SolidBrush(Color.White),e.Bounds);
}
int temp = listBoxName.SelectedIndex;
listBoxName.SelectedIndex = -1;
listBoxName.SelectedIndex = temp;