How do I bind a DataGridComboBoxColumn to EntityFr

2020-02-16 01:27发布

I'm trying to get a DataGridComboBoxColumn working with my ViewModel. Everything appears to work correctly but when I change the value of the combo box, the entity isn't changed.

The datacontext of the window has these properties:

ItemsSource

Public Property AllEnergySources() As ObservableCollection(Of EnergySourceViewModel)

SelectedItemBinding

  Private _CurrentEnergySource As EnergySourceViewModel
    Public Property CurrentEnergySource() As EnergySourceViewModel
        Get
            Return _CurrentEnergySource
        End Get
        Set(ByVal value As EnergySourceViewModel)
            _CurrentEnergySource = value
            OnPropertyChanged("CurrentEnergySource")
        End Set
    End Property

I feel the problem lies with how I populate CurrentEnergySource in the ViewModel that is the DataContext:

Sub New(SelectedEntity as EquipmentEnergySource)
     AllEnergySources = New ObservableCollection(Of EnergySourceViewModel)

    //Select all EnergySources from the EntityFramework
     Dim EnergyEntities = From esr in db.EnergySources Select esr

                //Loop through to convert Entity POCO to Collection of ViewModels
                For Each es In EnergyEntities
                    _AllEnergySources.Add(New EnergySourceViewModel(es))

                    //Optionally Set the newly created ViewModel to SelectedItemBinding object
                    If es.EnergySourceID = SelectedEntity.EnergySourceID Then
                        _CurrentEnergySource = _AllEnergySources.Last
                    End If
                Next
End Sub

When I create the backing collection for the combobox, if the model is the selected one, I set that viewmodel to be the CurrentEnergySource but after that point it is disconnected(and that's the problem)

What should I reference in CurrentEnergySource so that it updates the model when the combo box changes?

4条回答
乱世女痞
2楼-- · 2020-02-16 01:53

of course, the problem is in your binding, the DataGridComboBoxColumn automatically take one item from CurrentEnergySource, and the CurrentEnergySource don't have AllEnergySources on it, Whey you don't semply Use this,

            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding SelectedItemFromItemsSource}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding ItemsSource}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
查看更多
等我变得足够好
3楼-- · 2020-02-16 01:56

One thing that seems to be wrong is you should probably be using SelectedValueBinding not SelectedItemBinding.

Here's a sample that works ok for me:

<Page.Resources>
    <ViewModel:DataGridComboBoxViewModel x:Key="model"/>
    <Style x:Key="ElementStyle" TargetType="ComboBox">
        <Setter 
            Property="ItemsControl.ItemsSource" 
            Value="{Binding Path=DataContext.DetailItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" 
            />
    </Style>
</Page.Resources>

<Grid DataContext="{StaticResource model}">
    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            <DataGridComboBoxColumn Header="Combo" 
                                    DisplayMemberPath="Name" 
                                    SelectedValueBinding="{Binding DetailItem}" 
                                    ElementStyle="{StaticResource ElementStyle}"
                                    EditingElementStyle="{StaticResource ElementStyle}"
                                    >
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

public class DataItem : ViewModelBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; } 

    private DetailItem _detailItem;
    public DetailItem DetailItem
    {
        get { return _detailItem; }
        set
        {
            Debug.WriteLine(value != null
                                ? string.Format("Setting detail item to: {0}", value.Name)
                                : "Setting detail item to null.");

            Set(() => DetailItem, ref _detailItem, value);
        }
    }
}

public class DetailItem : ViewModelBase
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class DataGridComboBoxViewModel : ViewModelBase
{
    public DataGridComboBoxViewModel()
    {
        DetailItems = new List<DetailItem>
                          {
                              new DetailItem {Id = 0, Name = "Zero"},
                              new DetailItem {Id = 1, Name = "One"},
                              new DetailItem {Id = 2, Name = "Two"},
                              new DetailItem {Id = 3, Name = "Three"},
                          };

        Items = new List<DataItem>
                    {
                        new DataItem {Id = 0, Name = "Item 1", Description = "This is item 1"},
                        new DataItem {Id = 1, Name = "Item 2", Description = "This is item 2"},
                        new DataItem {Id = 2, Name = "Item 3", Description = "This is item 3"},
                        new DataItem {Id = 3, Name = "Item 4", Description = "This is item 4"},
                    };
    }

    public List<DataItem> Items { get; set; }
    public List<DetailItem> DetailItems { get; private set; }
}
查看更多
爷的心禁止访问
4楼-- · 2020-02-16 02:16

Have you tried a RelativeSource on the binding? usually I find when I'm binding to a column in a template etc the binding looks inside the binding of the control, not that of the datacontext of the view.

Try either:

"{Binding Path=DataContext.CurrentEnergySource, 
          RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},
          Mode=TwoWay}"

or

"{Binding ElementName=NameOfTheView, 
          Path=DataContext.CurrentEnergySource, 
          Mode=TwoWay}"

and then adding x:Name="NameOfTheView" to the View's attributes (below the xmlns place inside the > bracket)

查看更多
够拽才男人
5楼-- · 2020-02-16 02:17

My answer is you need to change the foreign key manually (I now change it in the setter of CurrentEnergySource, which is the SelectedItemBinding bound property)

     Private _CurrentEnergySource As EnergySourceViewModel
    Public Property CurrentEnergySource() As EnergySourceViewModel
        Get
            Return _CurrentEnergySource
        End Get
        Set(ByVal value As EnergySourceViewModel)
            _CurrentEnergySource = value
            Me.Model.EnergySourceID = value.Model.EnergySourceID
            OnPropertyChanged("CurrentEnergySource")
        End Set
    End Property

On load, populate the private backing store _CurrentEnergySource instead of the property to avoid all objects starting out with modified state

查看更多
登录 后发表回答