【问题标题】:ObservableCollection or List data bind with comboBox using MVVM?ObservableCollection 或 List 数据使用 MVVM 与组合框绑定?
【发布时间】:2011-12-29 12:24:21
【问题描述】:

我有 ObservableCollection 项,我想将此数据绑定到我的组合框。 如何使用组合框绑定数据? 我正在使用 MVVM 模式,所以建议我如何使用 MVVM 模式绑定数据

我正在尝试执行此代码但无法正常工作.. 在我的 XAML 页面中:

<ComboBox x:Name="comobo1" 
          DisplayMemberPath="CardTypeName" 
          SelectedValuePath="CardTypeID" 
          ItemsSource="{Binding Path=combodata}">    
</ComboBox>

在我的 ViewModel 中
Card 是我的模特)

 public ObservableCollection<Card> combodata = new ObservableCollection<Card>();
 foreach (var item in App.db.States)
 {
     Card c = new Card(item.StateName, item.StateID);
     combodata.Add(c);
 }

如何将此组合数据绑定到我的组合框 - 我做错了什么?

【问题讨论】:

    标签: c# .net wpf data-binding mvvm


    【解决方案1】:

    首先:您的combodata 具有private 访问修饰符而不是public。其次:combodata 必须是property,而不是field。而且你最好在你的类中添加 INotifyPropertyChanged 实现。

    【讨论】:

    • 它仍然是一个字段。将其更改为public ObservableCollection&lt;Card&gt; combodata { get; set; }
    【解决方案2】:
    private ObservableCollection<Card> _combodata;
    Public ObservableCollection<Card> comboData
    {
       get
       {
          if (_combodata == null)
             _combodata = new ObservableCollection<Card>();
          return _combodata;
       }
       set
       {
           if (value != _combodata)
               _combodata = value;
       }
    }
    
    
    <ComboBox x:Name="comobo1" 
          DisplayMemberPath="CardTypeName" 
          SelectedValuePath="CardTypeID" 
          ItemsSource="{Binding Path=comboData}">    
    </ComboBox>
    

    别忘了设置 DataContext 属性。

    【讨论】:

    • 在datacontext中我提供了哪些数据?
    • 你应该将你的组合框的 DataContext 属性或者他的父辈设置为你的 viewmodel 对象,它包含 ObservableCollection comboData
    【解决方案3】:

    代码存在以下问题。

    1.您不能绑定到私有字段或属性。它应该是公共财产。

    2.您只提供了ItemsSource="{Binding Path=combodata}",但没有提供来源。组合数据从何而来?

    ObservableCollection 没有任何作用,除非您的组合框项目在填充后不会更改。在这种情况下,List 可以很好地工作。

    要使其正常工作,请将您的组合数据更改为公共财产

    public ObservableCollection<Card> combodata {get;set;}
    

    那么,

    <ComboBox x:Name="comobo1" 
              DisplayMemberPath="CardTypeName" 
              SelectedValuePath="CardTypeID" 
              ItemsSource="{Binding Path=combodata}" ElementName=mainWindow>    
    </ComboBox>
    

    通过指定 ElementName,您是在告诉 WPF 绑定引擎查找 mainWindow 类的 combodata 属性。

    我希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      您必须绑定到应该实现INotifyPropertyChanged 的视图模型的公共属性。

      这是你应该做的:

      查看:

      <ComboBox x:Name="comobo1" DisplayMemberPath="CardTypeName" SelectedValuePath="CardTypeID" ItemsSource="{Binding Path=ComboData}" />
      

      视图模型:

      public class MyViewModel : INotifyPropertyChanged
          {
              private ObservableCollection<Card> comboData;
      
              public event PropertyChangedEventHandler PropertyChanged;
      
              public ObservableCollection<Card> ComboData
              {
                  get
                  {
                      return this.comboData;
                  }
      
                  set
                  {
                      if (this.comboData != value)
                      {
                          this.comboData = value;
                          this.NotifyPropertyChanged("ComboData");
                      }
                  }
              }
      
              private void NotifyPropertyChanged(String info)
              {
                  if (PropertyChanged != null)
                  {
                      PropertyChanged(this, new PropertyChangedEventArgs(info));
                  }
              }
          }
      

      编辑:您还需要设置视图的DataContext 属性。简单的方法是将 ViewModel 的实例影响到视图代码隐藏中的 DataContext 属性。

      【讨论】:

      • Ashwin,尝试检查 DataContext 属性。
      【解决方案5】:

      我的最佳猜测是您的 ComboBox 的 DataContext 未设置为您的 ViewModel 的实例

      我经常使用Snoop 来调试应用程序的DataContext 问题。它允许您查看您的可视化树,并查看所有控件的 DataContext 是什么。

      DataContext 是您的 UI 绑定到的数据。通常 DataContext 设置在 Visual Tree 中的较高位置,例如在 Window 对象上,尽管作为示例,以下代码行会将 ComboBox 的 DataContext 设置为 ViewModel 的新实例,然后您的 ComboBox 应该能够找到combodata 集合绑定到它。

      comobo1.DataContext = new MyViewModel();
      

      另外,将您的 combodataField(无获取/设置访问器方法)更改为 Property(有关示例,请参见 Dmitriy's Answer

      【讨论】:

      • 但我的 combo1 在 dataTemplate 中,而不是直接在我的 xaml 中使用。所以我无法在我的代码中获得组合框,以便将数据上下文提供给我的组合框
      • 如果我将组合框从 dataTemplate 中取出,我将获取数据,但我无法在 dataTemplate 中获取数据我如何使用所有代码都用完了 datatemplate 但不在 dataTemplate 中
      • @Ashwin 然后设置 UI 中包含模板化 ComboBox 的任何控件的 DataContext。当 ComboBox 被渲染时,它将从该控件继承它的 DataContext。
      【解决方案6】:

      您需要绑定到公共属性。在您的示例中,combodata 是私有的。

      【讨论】:

      • 您应该将其绑定到公共 (!) 属性 (!)。在您的代码中,您尝试绑定到公共字段。
      【解决方案7】:

      正确答案是:

      在 XAML 页面中“:

      <CollectionViewSource x:Key="comboBoxCollection" Source="{Binding comboData}"></CollectionViewSource>
        <DataTemplate x:Key="ComboBoxDataTemplate">
                  <Grid MinHeight="25">
                      <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="*" />
                      </Grid.ColumnDefinitions>
                        <ComboBox x:Name="comobo1" DisplayMemberPath="CardTypeName"   SelectedValuePath="CardTypeID" ItemsSource="{Binding Source={StaticResource comboBoxCollection }}">
                          </ComboBox>
                  </Grid>
               </DataTemplate>
      

      在 ViewModel 中:

       private ObservableCollection<Card> _combodata;
      
              public ObservableCollection<Card> comboData
              {
                  get
                  {
                      if (_combodata == null)
                          _combodata = new ObservableCollection<Card>();
                      return _combodata;
                  }
                  set
                  {
                      if (value != _combodata)
                          _combodata = value;
                  }
              }
      
        if (_objCardField.FieldTag == "State") 
                      {
                          cards = new Cards();
                          foreach (var item in App.db.States)
                          {
                              Card c = new Card(item.StateName, item.StateID);
                              comboData.Add(c);
                          }
                      }
      

      【讨论】:

        猜你喜欢
        • 2014-02-14
        • 2018-12-20
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 2011-06-13
        • 2015-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多