blueshift
blueshift

Reputation: 881

DatagridTemplateColumn/Combobox not showing ItemsSource

In my ViewModel, I have a BindableCollection (using Caliburn Micro) of a Unit class. The Unit class has two properties, UnitID (int) and UnitName (string). This collection is the ItemsSource for a ComboBox which is the DatagridTemplateColumn. I know that the BindableCollection is being populated but the Units are not being displayed in the ComboBox, nor are the UnitNames being displayed in the "From Unit" and "To Unit" columns.

Here is the important part of my ViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Vulcan.Entities;
using Vulcan.Conduits;
using Caliburn.Micro;

namespace Vulcan.ViewModels
{
    public class EditUnitConversionsViewModel : Screen, IActiveContentViewModel
    {
        IUnitConversionConduit _conversionConduit;
        IUnitConduit _unitConduit;
        EventAggregator _eventAggregator;

        public BindableCollection<UnitConversion> UnitConversions { get; set; }
        public int SelectedConversionIndex { get; set; }

        public BindableCollection<Unit> Units { get; set; }
        public int SelectedFromUnitIndex { get; set; }
        public int SelectedToUnitIndex { get; set; }


        public EditUnitConversionsViewModel(IUnitConversionConduit conversionConduit, IUnitConduit unitConduit, EventAggregator agg)
        {
            _conversionConduit = conversionConduit;
            _unitConduit = unitConduit;
            _eventAggregator = agg;

            Units = new BindableCollection<Unit>(_unitConduit.GetUnits());
            UnitConversions = new BindableCollection<UnitConversion>(_conversionConduit.GetUnitConversions().Select(c => new UnitConversion(c, _unitConduit)));
        }

Here are the Unit and UnitConversion classes:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Vulcan.Entities
{
    public class Unit
    {
        private int _unitID;
        public int UnitID
        {
            get { return _unitID; }
            set { _unitID = value; }
        }

        private string _unitName;
        public string UnitName
        {
            get { return _unitName; }
            set { _unitName = value; }
        }

        public Unit(int unitID, string unitName)
        {
            this.UnitID = unitID;
            this.UnitName = unitName;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Vulcan.Entities
{
    public class UnitConversion
    {
        public int UnitConversionID { get; set; }

        public int FromUnitID { get; set; }
        public int ToUnitID { get; set; }

        //Ex. meters to millimeters: ConversionFactor = 1000, Offset = 0
        // Fahrenheit to Celsius: Conversion Factor = 0.5556, Offset = 17.7778
        public double ConversionFactor { get; set; }
        public double Offset { get; set; }

        public UnitConversion(int id, int fromUnit, int toUnit, double conversionFactor, double offset)
        {
            this.UnitConversionID = id;
            this.FromUnitID = fromUnit;
            this.ToUnitID = toUnit;
            this.ConversionFactor = conversionFactor;
            this.Offset = offset;
        }
    }
}

Here is my current XAML:

<DataGrid.Columns>
    <DataGridTemplateColumn Header="From Unit" Width="*">
        <DataGridTemplateColumn.CellTemplate>
             <DataTemplate>
                  <ComboBox DisplayMemberPath="UnitName" SelectedValuePath="UnitID" 
                                            SelectedValue="{Binding Path=FromUnitID}"
                                            ItemsSource="{Binding Path=Units}" />
             </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn Header="To Unit" Width="*">
         <DataGridTemplateColumn.CellTemplate>
              <DataTemplate>
                  <ComboBox DisplayMemberPath="UnitName" SelectedValuePath="UnitID" 
                                            SelectedValue="{Binding Path=ToUnitID}"
                                            ItemsSource="{Binding Units}" />
               </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
     </DataGridTemplateColumn>
     <DataGridTextColumn Header="Conversion Factor" Binding="{Binding ConversionFactor}" Width="*" />
     <DataGridTextColumn Header="Offset" Binding="{Binding Offset}" Width="*" />

Here is a screenshot of the DataGrid: enter image description here

What do I need to change in my XAML to get the Units collection to show-up in the combo boxes?

Upvotes: 1

Views: 1695

Answers (2)

Martin Grundy
Martin Grundy

Reputation: 284

You do have have access to the Units collection in the DataGrid row. You only have access to the properties in the UnitConversion class (i.e. the class that the row represents), to bind to that collection you would need to do something like:

<ComboBox DisplayMemberPath="UnitName" 
          SelectedValuePath="UnitID" 
          SelectedValue="{Binding Path=FromUnitID}"
          ItemsSource="{Binding DataContext.Units, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}" />

Upvotes: 2

Rang
Rang

Reputation: 1372

I write some code according to your description.

  <DataGrid x:Name="dg" ItemsSource="{Binding LstUnitC}" AutoGenerateColumns="False" >
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="From Unit" Width="*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox DisplayMemberPath="UnitName"  ItemsSource="{Binding Units}"
                                            />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

            </DataGrid.Columns>
        </DataGrid>

background:

private List<UnitConversions> lstunitc;

        public List<UnitConversions> LstUnitC
        {
            get { return lstunitc; }
            set { lstunitc = value; }
        }


        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
            List<Units> lstunit = new List<Units>();
            Units u = new Units();
            u.UnitName = "asd";

            lstunit.Add(u);
            u = new Units();
            u.UnitName = "asd1";

            lstunit.Add(u);


            LstUnitC = new List<UnitConversions>();
            UnitConversions uc = new UnitConversions();
            uc.Units = lstunit;
            LstUnitC.Add(uc);
            dg.ItemsSource = LstUnitC;
        }



    }

    public class Units
    {
        private string _UnitName;

        public string UnitName
        {
            get { return _UnitName; }
            set { _UnitName = value; }
        }

    }

    public class UnitConversions
    {
        private List<Units> units;

        public List<Units> Units
        {
            get { return units; }
            set { units = value; }
        }


    }

make sure Units is a list and the list is a member of UnitConversion Class.

Upvotes: 1

Related Questions