ComboBox- เหตุการณ์ SelectionChanged มีค่าเก่าไม่ใช่ค่าใหม่


93

C #, .NET 4.0, VS2010

ใหม่สำหรับ WPF ฉันมี ComboBox บน MainWindow ของฉัน ฉันติดเหตุการณ์ SelectionChanged ของกล่องคำสั่งผสมดังกล่าว อย่างไรก็ตามถ้าฉันตรวจสอบค่าของกล่องคำสั่งผสมในตัวจัดการเหตุการณ์มันมีค่าเก่า ฟังดูเหมือนเหตุการณ์ "SelectionChanging" มากกว่าเหตุการณ์ SelectionChanged

ฉันจะรับค่าใหม่ของ ComboBox ได้อย่างไรหลังจากการเลือกเกิดขึ้นจริง

ปัจจุบัน:

this.MyComboBox.SelectionChanged += new SelectionChangedEventHandler(OnMyComboBoxChanged);

...
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = this.MyComboBox.Text;
}

หมายเหตุฉันจะได้รับพฤติกรรมเดียวกันนี้ถ้าฉันใช้วัตถุที่ส่งผ่านใน args เหตุการณ์ egeOriginalSource


2
ฉันเพิ่งสะดุดกับปัญหาเดียวกัน - ขอบคุณ! นั่นเป็นบั๊กจริงหรือไม่และควรได้รับการตั้งชื่อSelectionChangingตั้งแต่แรกหรือไม่?
ม.ค.

คำตอบ:


110

ตาม MSDN e.AddedItems:

รับรายการที่มีรายการที่ถูกเลือก

คุณสามารถใช้:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = (e.AddedItems[0] as ComboBoxItem).Content as string;
}

คุณยังสามารถใช้SelectedItemถ้าคุณใช้stringค่าItemsจากsender:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = (sender as ComboBox).SelectedItem as string;
}

หรือ

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;
}

เนื่องจากทั้งสองอย่างContentและSelectedItemเป็นวัตถุจึงควรใช้วิธีการที่ปลอดภัยกว่า.ToString()แทนas string


11
น่าสนใจ ... มันมีค่าใหม่ และ RemovedItems มีไฟล์. ชื่อเหตุการณ์นั้นเป็นชื่อเล็กน้อยหากเรียกชื่อผิดอย่างน้อย IMHO เมื่อฉันเห็น SelectionChanged ฉันคาดว่าสถานะของวัตถุจะเปลี่ยนไป ฉันเห็นว่าสิ่งนี้ให้ข้อมูลเพิ่มเติมแก่เราเล็กน้อยได้อย่างไร
Matt

1
ใช่ฉันคิดว่าเป็นเพราะการเปลี่ยนแปลงเกิดขึ้น แต่ไม่ได้มุ่งมั่น? นั่นเป็นเพียงการคาดเดา คุณอาจสามารถรับข้อความของรายการที่เลือกดูการแก้ไขของฉัน
SwDevMan81

3
ComboBox.SelectedItemไม่มีคุณสมบัติที่เรียกว่าTextแต่คุณสามารถทำได้ComboBox.SelectedItem as string(แม้ว่าจะใช้ได้ผลก็ต่อเมื่อคุณใช้stringสำหรับItems- ไม่ได้ทดสอบอย่างอื่น)
musefan

1
เพียงแค่ string text = (string) e.AddedItems [0];
Igor Semin

1
หวังว่าฉันจะให้ 2 อัพคำตอบของคุณช่วยฉันสองครั้งใน 2 ครั้งที่แตกต่างกัน
Upulie Han

62

ค่าที่ถูกต้องในการตรวจสอบที่นี่คือคุณสมบัติ SelectedItem

ComboBox คือการควบคุมแบบคอมโพสิตโดยมีสองส่วนคือ:

  1. ส่วนข้อความ : ค่าในส่วนนี้สอดคล้องกับคุณสมบัติTextของ ComboBox
  2. ส่วนตัวเลือก (เช่นส่วน "ดรอปดาวน์"): รายการที่เลือกในส่วนนี้สอดคล้องกับคุณสมบัติSelectedItem

ส่วนขยาย ComboBox

ภาพด้านบนถูกถ่ายทันทีหลังจากขยาย ComboBox (กล่าวคือก่อนเลือกค่าใหม่) ณ จุดนี้ทั้งTextและSelectedItemคือ "ข้อมูล" โดยถือว่ารายการ ComboBox เป็นสตริง หากรายการ ComboBox เป็นแทนทุกค่าของ Enum ที่เรียกว่า "LogLevel" SelectedItemปัจจุบันจะLogLevel.Info

เมื่อมีการคลิกรายการในรายการแบบเลื่อนลงค่าของSelectedItemจะเปลี่ยนไปและเหตุการณ์SelectionChangedจะเพิ่มขึ้น ข้อความคุณสมบัติไม่ได้ปรับปรุง แต่เป็นข้อความบางส่วนจะไม่ปรับปรุงจนกระทั่งหลังจากSelectionChangedจัดการเสร็จสิ้น สิ่งนี้สามารถสังเกตได้โดยการใส่เบรกพอยต์ในตัวจัดการและดูที่ตัวควบคุม:

ComboBox ที่เบรกพอยต์ในตัวจัดการ SelectionChanged

เนื่องจากยังไม่ได้อัปเดตส่วนข้อความในตอนนี้คุณสมบัติTextจะส่งคืนค่าที่เลือกไว้ก่อนหน้านี้


2
การขยายที่สมบูรณ์และช่วยให้ตระหนักว่าการผูกของฉันอยู่ในคุณสมบัติข้อความแทนที่จะเป็น SelectedItem ที่ถูกต้อง
cmousset

1
@DaveKidder ตัวอย่างที่ดี! +1
Ryan Wilson

47

ใช้เหตุการณ์ DropDownClosed แทน selectionChanged ถ้าคุณต้องการค่าปัจจุบันของกล่องคำสั่งผสม

private void comboBox_DropDownClosed(object sender, EventArgs e)
{
   MessageBox.Show(comboBox.Text) 
}

เป็นเรื่องง่ายที่


10
@jvelez ฉันคิดว่ามันจะไม่ทำงานเมื่อใช้แป้นพิมพ์
NoviceProgrammer

ที่ห่วย NoviceProgrammer ผู้รู้ ... !
ซ่อน

10

สิ่งนี้ใช้ได้ผลสำหรับฉัน:

private void AppName_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   ComboBoxItem cbi = (ComboBoxItem)AppName.SelectedItem;
   string selectedText = cbi.Content.ToString();
}

มีเพียง SelectedItem เท่านั้นที่ได้รับการเติมข้อมูลด้วยรายการใหม่ไม่ใช่ SelectedValue
mauris

8

สิ่งนี้ใช้ได้ผลสำหรับฉัน:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;            
}

สิ่งนี้สำคัญมาก คำตอบที่ได้รับการยอมรับไม่ได้อย่างชัดเจนแสดงให้เห็นว่ามีความถูกต้องsender SelectedItem
Jess

สิ่งนี้ทำให้เกิดข้อยกเว้นสำหรับฉัน: System.NullReferenceException: 'การอ้างอิงวัตถุไม่ได้ตั้งค่าเป็นอินสแตนซ์ของวัตถุ' (... เป็น System.Windows.Controls.ComboBoxItem) ส่งคืนค่า null
Ali Safari

@ เจส - ฉันเห็นด้วย 100% คำตอบที่ยอมรับไม่ได้ผลสำหรับฉัน อันนี้ทำ
BoundForGlory

4

เหตุการณ์ต่อไปนี้จะเริ่มทำงานสำหรับการเปลี่ยนแปลงใด ๆ ของข้อความใน ComboBox (เมื่อดัชนีที่เลือกมีการเปลี่ยนแปลงและเมื่อข้อความถูกเปลี่ยนแปลงโดยการแก้ไขด้วย)

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />

1
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}

7
โปรดอย่าให้คำตอบแบบใช้รหัสเท่านั้น โปรดให้คำอธิบายว่าเหตุใดโซลูชันของคุณจึงเป็นคำตอบ
Lee Taylor

System.InvalidCastException: 'ไม่สามารถส่งวัตถุประเภท' System.String 'เพื่อพิมพ์' System.Data.DataRowView '
Ali Safari

1

ตัวเลือกที่สองใช้ไม่ได้สำหรับฉันเพราะองค์ประกอบ. Text อยู่นอกขอบเขต (C # 4.0 VS2008) นี่คือทางออกของฉัน ...

string test = null;
foreach (ComboBoxItem item in e.AddedItems)
{
   test = item.Content.ToString();
   break;
}

0

ฉันต้องการแก้ปัญหานี้ใน VB.NET นี่คือสิ่งที่ฉันมีที่ดูเหมือนจะใช้งานได้:

Private Sub ComboBox1_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles ComboBox_AllSites.SelectionChanged
   Dim cr As System.Windows.Controls.ComboBoxItem = ComboBox1.SelectedValue
   Dim currentText = cr.Content
   MessageBox.Show(currentText)
End Sub

0

เป็นเรื่องแปลกที่ SelectedItem เก็บข้อมูลใหม่ในขณะที่ SelectedValue ไม่มี ฟังดูเป็นข้อบกพร่องสำหรับฉัน หากรายการของคุณใน Combobox เป็นวัตถุอื่นที่ไม่ใช่ ComboBoxItems คุณจะต้องมีสิ่งนี้: (ของฉันComboBoxมีKeyValuePairs)

var selectedItem = (KeyValuePair<string, string>?)(sender as ComboBox).SelectedItem;
if (!selectedItem.HasValue)
    return;

string selectedValue = selectedItem.Value.Value;  // first .Value gets ref to KVPair

ComboBox.SelectedItemสามารถเป็นโมฆะในขณะที่ Visual Studio บอกฉันว่าKeyValuePairไม่สามารถเป็นโมฆะได้ นั่นเป็นเหตุผลที่ผมโยนSelectedItemไป KeyValuePair<string, string>?nullable แล้วฉันจะตรวจสอบว่ามีค่าอื่นที่ไม่ใช่selectedItem nullแนวทางนี้ควรใช้ได้กับสินค้าประเภทที่คุณเลือกจริงๆ


0

หากคุณต้องการSelectionChangedกิจกรรมจริงๆคำตอบที่ดีที่สุดคือคำตอบของ SwDevMan81 อย่างไรก็ตามหากคุณเริ่มต้นด้วย WPF คุณอาจต้องการเรียนรู้วิธีการทำสิ่งต่างๆด้วยวิธี WPF ซึ่งแตกต่างจาก Windows Forms สมัยก่อนที่เคยพึ่งพาเหตุการณ์เช่นSelectionChangedด้วยรูปแบบ WPF และ Model View ViewModel คุณควร ใช้การผูก นี่คือตัวอย่างโค้ด:

// In the Views folder: /Views/MyWindow.xaml:
// ...
<ComboBox ItemsSource="{Binding MyViewModel.MyProperties, RelativeSource={RelativeSource AncestorType=Window}}"
         SelectedItem="{Binding MyViewModel.MyProperty  , RelativeSource={RelativeSource AncestorType=Window}}" />
// ...



// In the Views folder: /Views/MyWindow.xaml.cs:
public partial class MyWindow : Window
{
    public  MyViewModelClass MyViewModel {
        get { return _viewModel; }
        private set { _viewModel = value;}
    }

    public MyWindow()
    {
        MyViewModel.PropertyChanged += MyViewModel_PropertyChanged;

    }

    void MyViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "MyProperty")
        {
            // Do Work
            // Put your logic here!
        }
    }
}

using System.ComponentModel;

// In your ViewModel folder: /ViewModels/MyViewModelClass.cs:
public class MyViewModelClass : INotifyPropertyChanged
{
    // INotifyPropertyChanged implementation:
    private void NotifyPropertyChanged(string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
    public event PropertyChangedEventHandler PropertyChanged;

    // Selected option:
    private string _myProperty;
    public  string  MyProperty {
        get { return _myProperty; }
        set { _myProperty = value; NotifyPropertyChanged("MyProperty"); }
    }

    // Available options:
    private List<string> _myProperties;
    public  List<string>  MyProperties {
        get { return _myProperties; }
        set { _myProperties = value; NotifyPropertyChanged("MyProperties"); }
    }

}

0
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int NewProjID = (e.AddedItems[0] as kProject).ProjectID;
    this.MyProject = new kProject(NewProjID);
    LoadWorkPhase();
}

การใช้โดยe.AddedItems[0] as kProjectที่ kProject เป็นคลาสที่เก็บข้อมูลที่ใช้งานได้สำหรับฉันเนื่องจากเป็นค่าเริ่มต้นของ RemovedItems [0] ก่อนที่ฉันจะสร้างความแตกต่างอย่างชัดเจนนี้ ขอบคุณ SwDevMan81 สำหรับข้อมูลเบื้องต้นที่ตอบคำถามนี้ให้ฉัน


0

อย่าซับซ้อนโดยไม่มีเหตุผล การใช้คุณสมบัติ SelectedValue คุณสามารถรับค่า ComboBox ที่เลือกได้อย่างง่ายดายเช่นนี้ YourComboBoxName.SelectedValue ToString ()

เบื้องหลังคุณสมบัติ SelectedValue ถูกกำหนดเป็น: SelectedValue {get; set;} ซึ่งหมายความว่าคุณสามารถใช้เพื่อรับหรือตั้งค่าของ ComboBox

การใช้ SelectedItem ไม่ใช่วิธีที่มีประสิทธิภาพในการรับค่า ComboBox เนื่องจากต้องใช้ ramifications จำนวนมาก


0

คุณสามารถตรวจสอบคุณสมบัติ SelectedIndex หรือ SelectedValue หรือ SelectedItem ในเหตุการณ์ SelectionChanged ของตัวควบคุม Combobox


0

จากเหตุการณ์ SelectionChanged ของ combobox คุณจะได้รับข้อความรายการที่เลือกดังนี้:

        private void myComboBox_SelectionChanged (object sender, SelectionChangedEventArgs e)
        {
        ComboBoxItem comboBoxItem = (ComboBoxItem) e.AddedItems[0];
        string selectedItemText = comboBoxItem.Content.ToString();
        }

-3

สิ่งนี้น่าจะเหมาะกับคุณ ...

int myInt= ((data)(((object[])(e.AddedItems))[0])).kid;

2
คุณอธิบายได้ไหมว่าสิ่งนี้ตอบคำถามได้อย่างไร
Nathan Tuggy

-3

ฉันแก้ไขสิ่งนี้โดยใช้เหตุการณ์ DropDownClosed เนื่องจากสิ่งนี้เริ่มทำงานเล็กน้อยหลังจากเปลี่ยนค่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.