Binding ObservableCollection to DataGrid ComboBox?

爱⌒轻易说出口 提交于 2019-12-25 08:27:33

问题


I am trying to bind the items of the ComboBox with an ObservableCollection, I have been successfully binding them to a StaticResource,

The XAML, Nursing_Home_Name is the SQL Server Table and this code works fine for me.

<Window.Resources>
    <local:CollectionsLists x:Key="StaticNursingHomeList" />
</Window.Resources>


<DataGridTemplateColumn Width="120" Header="施設名称">
   <DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
         <TextBlock Text="{Binding UpdateSourceTrigger=PropertyChanged,
                           Path=Nursing_Home_Name}" />
      </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
   <DataGridTemplateColumn.CellEditingTemplate>
       <DataTemplate>
          <ComboBox Text="{Binding Path=Nursing_Home_Name,
                           UpdateSourceTrigger=PropertyChanged}"
                           ItemsSource="{Binding NursingHome, 
                           Source={StaticResource StaticNursingHomeList}}" />
       </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

And code behind,

class CollectionsLists
    {     
        public static List<string> NursingHome { get; set; } 
        var homeNames = Database.GetNursingHomeNames(_nursingHomeSection);
        if (homeNames != null)
        {
           NursingHome = new List<string>();
           foreach (var item in homeNames)
           {
                NursingHome.Add(item);
           }
        }
    }

Now for the problem code,

I am finding it very hard to debug the XAML on what I am doing wrong.

This is the code behind,

public partial class MainWindow : INotifyPropertyChanged
    {        
        public MainWindow()
        { 
            DataContext = this; 
            InitializeComponent();
        }

        private ObservableCollection<string> _nursingHomeNames = new ObservableCollection<string>();

        public ObservableCollection<string> NursingHomeNames
           {
               get { return _nursingHomeNames; }
               set
               {
                   _nursingHomeNames = value;
                   NotifyPropertyChanged();
               }
           }
}

And I cannot show the multitude of ways that I have tried to get the XAML to work, but instead I will post what I thought was the closest to getting it to work,

The XAML, Nursing_Home_Name is the SQL Server Table BTW

<DataGridTemplateColumn Width="120" Header="施設名称">
   <DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
         <TextBlock Text="{Binding UpdateSourceTrigger=PropertyChanged,
                           Path=Nursing_Home_Name}" />
      </DataTemplate>
   </DataGridTemplateColumn.CellTemplate>
   <DataGridTemplateColumn.CellEditingTemplate>
       <DataTemplate>
          <ComboBox Text="{Binding Path=Nursing_Home_Name,
                           UpdateSourceTrigger=PropertyChanged}"
                           ItemsSource="{Binding NursingHomeNames}" />
       </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

What do I need to add to get this to bind correctly?


回答1:


What do I need to add to get this to bind correctly?

Since NursingHomeNames is a property of the parent window and the DataContext of the ComboBox is an item in the ItemsSource collection of the DataGrid, you need to specify the window as the source of the binding. Try this:

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <ComboBox ItemsSource="{Binding Path=NursingHomeNames, RelativeSource={RelativeSource AncestorType=Window}}"
                          SelectedItem="{Binding Path=Nursing_Home_Name}"/>
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>



回答2:


Binding in WPF uses what's called the DataContext of current context. In your case DataContext is of your MainWindow and know this that you can't have two of these in one context for example you can declare another one inside your DataGrid but you can't use the one from MainWindow any more. In short you can't bind to Nursing_Home_Name and NursingHomeNames in the same context.

Ok what's the solution then?

You have to bring one of these properties to the other context. It's simpler to bring your Nursing_Home_Name to your MainWindow like this:

public partial class MainWindow : INotifyPropertyChanged
{        
    public MainWindow()
    { 
        DataContext = this; 
        InitializeComponent();
    }

    private ObservableCollection<string> _nursingHomeNames = new ObservableCollection<string>();

    public ObservableCollection<string> NursingHomeNames
       {
           get { return _nursingHomeNames; }
           set { _nursingHomeNames = value; }
       }

    public string Nursing_Home_Name //Unconventional name. But I kept your naming
    {
        get { return GetNursingHomeNameFromDB(); }
        set 
        {
            SaveNursingHomeName(value); 
            NotifyPropertyChanged("Nursing_Home_Name");
        }
    }
}

This will work if you implement GetNursingHomeNameFromDB and SaveNursingHomeName.

One final tip: ObservableCollection<T> doesn't require NotifyPropertyChanged() it's built in.



来源:https://stackoverflow.com/questions/41530138/binding-observablecollection-to-datagrid-combobox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!