2008-09-14 10 views
43

मैं किसी ऐसे व्यक्ति के लिए एक उदाहरण बना रहा हूं जिसने अभी तक एहसास नहीं किया है कि ListBox जैसे नियंत्रणों में तार नहीं होना चाहिए; वह ListBox से डेटा वापस पाने के लिए जटिल पार्सिंग हुप्स के माध्यम से स्वरूपित तारों को संग्रहित कर रहा था और मैं उसे दिखाना चाहता हूं कि वहां एक बेहतर तरीका है।मैं सूची बॉक्स को अपने आइटम टेक्स्ट को रीफ्रेश कैसे कर सकता हूं?

मैंने देखा कि अगर मेरे पास ListBox में संग्रहीत ऑब्जेक्ट है तो ToString को प्रभावित करने वाला मान अपडेट करें, 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, लेकिन इस कोई प्रभाव नहीं पड़ा। (कारण मैं फ़ील्ड का उपयोग कर रहा हूं क्योंकि यह एक उदाहरण है और मुझे कुछ दर्जन लाइनों को जोड़ने की तरह महसूस नहीं होता है, जिनके पास मैं प्रदर्शित कर रहा हूं, उसके साथ कुछ लेना देना नहीं है।)

ईमानदारी से मैंने कभी अपडेट करने का प्रयास नहीं किया है पहले इस तरह की जगहें; अतीत में मैं हमेशा आइटम जोड़ रहा/हटा रहा हूं, उन्हें संपादित नहीं कर रहा हूं। तो मैंने कभी नहीं देखा है कि मुझे नहीं पता कि यह काम कैसे करें।

तो मुझे क्या याद आ रही है?

उत्तर

24

बाइंडिंगलिस्ट बाइंडिंग को स्वयं ही अपडेट करता है।

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); 
      } 
     } 
    } 
} 
+0

यह वर्तमान में स्वीकृत उत्तर की तुलना में वास्तव में कम काम है। शानदार! मैंने एक उदाहरण शामिल करने के लिए अपनी पोस्ट संपादित की। – OwenP

+1

आप वास्तव में उसमें सुधार कर सकते हैं जो मुझे लगता है। आप माता-पिता और बाल बाइंडिंग को नियंत्रित करने के लिए लागू कर सकते हैं जिसका मतलब है कि आप _SelectedIndexChanged ईवेंट हैंडलर के बिना कर सकते हैं। मैं सटीक कोड भूल जाता हूं ..... :( – Quibblesome

+0

मैंने उदाहरण अपडेट किया है, चयनित इंडेक्स चेंजेड इवेंट हैंडलर को हटा रहा है और लोड हैंडलर में 2 नई लाइनों के साथ बदल रहा है। :) – Quibblesome

9

डेटासोर्स प्रॉपर्टी और बाइंडिंग स्रोत ऑब्जेक्ट का उपयोग डेटासोर्स और सूची बॉक्स की डेटासोर्स संपत्ति के बीच करें। फिर उसे रीफ्रेश करें।

अद्यतन जोड़ा गया उदाहरण।

तो जैसा

:

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 
+0

बहुत बढ़िया,:

तो अगर मैं कहीं वर्ग Color बदलने के लिए, आप बस इसे के रूप में अद्यतन कर सकते हैं। किसी कारण से, WinForms में बाध्यकारी डेटा कभी भी समाधान के रूप में मुझ पर कूद नहीं जाता है इससे कोई फर्क नहीं पड़ता कि मैं इसे WPF में कितना उपयोग करता हूं। – OwenP

+0

हेह यह इससे भी अधिक मजेदार होता था। कुछ ऐसा: ((CurrencyManager) यह। बाइंडिंग कॉन्टेक्स्ट [ListBox1])। ताज़ा करें(); बाइंडिंग कॉन्टेक्स्ट से "छुपा" ऑब्जेक्ट प्राप्त करना और उसके बाद उसे मुद्रा प्रबंधक को कास्ट करना। हालांकि यह सी # है क्योंकि मैंने इसे कभी भी VB.NET में नहीं किया है। – Quibblesome

+0

यह एक अच्छा जवाब है, लेकिन आखिरकार जीवाणु के सुझाव का उपयोग बाध्यकारी सूची का उपयोग करने के लिए कम काम होता है। – OwenP

-1

मैं vb.net के बारे में है, लेकिन सी # में आप डेटा स्रोत का उपयोग करना चाहिए ज्यादा पता नहीं है और फिर listbox.bind() फोन करके बाँध यह चाल करना होगा।

+2

teh internets के लिए Thats। WinForm में रुचि रखने वाले इस व्यक्ति को मेथिंक। – Quibblesome

1

यदि आप ListBox से प्राप्त करते हैं तो RefreshItem संरक्षित विधि है जिसे आप कॉल कर सकते हैं। बस इस विधि को अपने स्वयं के प्रकार में दोबारा खोलें।

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

फिर अपनी डिजाइनर फ़ाइल को अपने स्वयं के प्रकार (इस मामले में, ListBox2) का उपयोग करने के लिए बदलें।

32

मैं इस वर्ग का उपयोग करता हूं जब मुझे अद्यतन सूची बॉक्स होना चाहिए।

सूची में ऑब्जेक्ट को अपडेट करें और उसके बाद शामिल विधियों में से किसी एक को कॉल करें, अगर आपके पास इंडेक्स उपलब्ध है या नहीं। यदि आप सूची में निहित वस्तु को अपडेट कर रहे हैं, लेकिन आपके पास इंडेक्स नहीं है, तो आपको RefreshItems को कॉल करना होगा और सभी आइटम अपडेट करना होगा।

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

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

नोट, 'RefreshItem' केवल तभी काम करता है जब' DisplayMember' प्रॉपर्टी सेट हो। –

0

यह थोड़ा सा व्यावसायिक है, लेकिन यह काम करता है। मैंने अभी आइटम को हटा दिया और जोड़ा (इसे फिर भी चुना)। सूची को "प्रदर्शित और परिवर्तित" संपत्ति के अनुसार क्रमबद्ध किया गया था, फिर, मेरे लिए ठीक था। दुष्प्रभाव यह है कि अतिरिक्त घटना (सूचकांक परिवर्तित) उठाया गया है।

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

क्यों वोट नीचे ?? – nawfal

+0

यह हमेशा चयनित आइटम को सूची बॉक्स के अंत में रखेगा! –

-3

तो objLstTypes अपने ListBox नाम उपयोग objLstTypes.Items है।ताज़ा(); आशा है कि यह काम करता है ...

+0

कोई ताज़ा विधि नहीं है। –

29
lstBox.Items[lstBox.SelectedIndex] = lstBox.SelectedItem; 
+5

यह वास्तव में एक वैध जवाब है! – nawfal

+3

यह मेरा वोट प्राप्त करता है! सरल, कोड के किसी भी नए वर्ग या पैराग्राफ जोड़ने के बिना किया जा सकता है। यह सब मुझे चाहिए था। – Rob

+1

शानदार - सरल और काम पूरा हो जाता है, धन्यवाद! –

16
typeof(ListBox).InvokeMember("RefreshItems", 
    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, 
    null, myListBox, new object[] { }); 
+0

मुझे यह उपयोगी मिला: इसका उपयोग सूची बॉक्स को गतिशील रूप से रीफ्रेश करने के लिए किया जा सकता है –

0

आप की तरह एक ड्रॉ विधि का उपयोग करते:

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; 

और Color अद्यतन करेगा सिर्फ एक और समाधान :)