【问题标题】:Accessing data in a listbox访问列表框中的数据
【发布时间】:2011-12-19 15:06:40
【问题描述】:

嘿,我需要访问我在 WPF 中创建的列表框中的项目。我现在拥有的是用户可以将一个新的类对象添加到 ListBox.ItemsSource 绑定到的 ObservableCollection。这个类中有数据,这些数据用于组合框、文本框和其他类似的简单事物中。

我所做的实际上是基于 windowsclient.net 的一个 tut 视频

    //Here's What I have so far
    <ListBox x:Name="MyList" Width = "300" Height = 300">
         <ListBox.ItemTemplate>
              <DataTemplate>
                   <StackPanel Orientation="Vertical">
                        <TextBlock x:Name="ItemName" 
                         Text={Binding Path=PersonName}/>
                        <ComboBox x:Name="NumberOfRes" 
                         SelectedIndex="0"
                         SelectionChanged="NumberOfRes_SelectionChanged"
                         ItemsSource={Binding Path=ListOfNums}/>
                   </StackPanel>
              </DataTemplate>
         </ListBox.ItemTemplate>
    </ListBox>

    //ListOfNums
    private ObservableCollection<int> _listofNums = 
                     new ObservableCollection<int>()
    { 1,2,3,4,5,6,7,8 };
    public ObservableCollection<int> ListOfNums
    {
         get{return _listOfNums;}
    }

    //class Resident
    public class Resident
    {
        public string personName {get;set;}
    }

所以我有这个工作。我有一个添加新类对象的按钮,每个对象都通过数据绑定正确设置了数据。因此,当添加新对象时,我可以看到我的默认 personName,并且我有一个填充了 ListOfNums 整数的组合框。

我的问题是我不知道如何访问这些“子对象”(请原谅我是 WPF 新手,不知道正确的术语)正在选择什么。我想知道当引发 selectionChange 事件时我的组合框的 SelectedItem 是什么,或者当用户在文本框中键入内容时我的新 personName 设置为什么。因此,用户在 listBox 中选择这些 ItemTemplate 对象之一,并且该项目具有组合框和用户单击的其他 UI 控件。当用户单击这些 UI 控件之一时,会发生一些数据更改。

我尝试了((Resident)MyList.SelectedItem).personName 和其他几种方法,只是为了看看我是否可以访问数据并对其进行操作。 Now the funny thing is that my comboBox in the ItemTemplate has a selection changed event that is called when the selection is changed, but I can't access the data!

提前致谢!

【问题讨论】:

    标签: c# wpf data-binding combobox listbox


    【解决方案1】:

    以下示例使用 ViewModel (VM)。如果您将新居民添加到 Residents 集合中,它们将显示在列表框中。只是一个提示,如果你最终为你的控件命名很多,那么你没有正确地进行数据绑定。

    XAML:

    <ListBox ItemsSource="{Binding Path=Residents}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Path=PersonName}" />
                    <ComboBox 
                        ItemsSource="{Binding Path=DataContext.ListOfNums, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" 
                        SelectionChanged="NumberOfRes_SelectionChanged" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    后面的代码:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            DataContext = new VM();
        }
    
        private void NumberOfRes_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            Resident resident = comboBox.DataContext as Resident;
            int number = (int)comboBox.SelectedItem;
        }
    }
    
    public class VM
    {
        public VM()
        {
            Residents = new ObservableCollection<Resident>() { new Resident() { PersonName = "AAA" }, new Resident() { PersonName = "BBB" } };
        }
    
        public ObservableCollection<Resident> Residents { get; private set; }
    
        public IEnumerable<int> ListOfNums
        {
            get { return new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8 }; }
        }
    }
    
    public class Resident
    {
        public string PersonName { get; set; }
    }
    

    【讨论】:

      【解决方案2】:

      有多种方法可以实现您的目标。最简单的方法是在您的 ViewModel 上放置一个 SelectedItem 属性。

      您的 ViewWModel 将如下所示...

      public class MyViewModel : INotifyPropertyChanged
      {
            ObservableCollection<Resident> Residents { get; }
      
            private Resident _selectedItem;
            public Resident SelectedItem
            {
                 get { return _selectedItem; }
                 set
                 {
                      _selectedItem = value;
                      PropertyChangedEventHandler handler = PropertyChanged;
                      if(handler != null)
                          handler(this, new PropertyChangedEventArgs("SelectedItem");
                 }
            }
      }
      

      在您的视图中,将DataContext 设置为此ViewModel 的一个实例,其中您的ListBox.ItemsSource 绑定到Residents,而您的ListBox.SelectedItem 绑定到SelectedItem

      <ListBox ItemsSource="{Binding Path=Residents}" 
               SelectedItem="{Binding Path=Selectedtem, Mode=TwoWay}" />
      

      如果您想在选择更改时执行操作,请注意 SelectedItem 属性的设置器,它将包含新选择的项目。

      编辑

      刚刚注意到您的Resident 模型没有实现INotifyPropertyChanged,它需要这样做才能将更改传播到下游。然后,您可以在SelectedItem 属性中提到的给定属性的设置器中获取数据将更改的点。

      【讨论】:

      • 没有。我有一个继承自它的 ViewModelBase 类,感谢您的快速回复。
      猜你喜欢
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      相关资源
      最近更新 更多