Mech0z
Mech0z

Reputation: 3647

Get datagrid to create columns with unknown types using reflection

I have 2 ViewModels

Case1ViewModel : ViewModelBase, ITestInterface
Case2ViewModel : ViewModelBase, ITestInterface

They both inherit from ITestInterface which is empty

I then have an

ObservableCollection<ITestInterface>

I then have a DataGrid I would like to databind to the ViewModels

At runtime it will be either a Case1ViewModel or Case2ViewModel , and I then want the datagrid to autogenerate the columns which will be different depending on which ViewModel is in the list(Only one type of ViewModel at a time), atm it is just empty (As it just looks at the interface) but I would think it would be possible to make this with some sort of reflection?

Example

The collection I bind to

    public ObservableCollection<ITestInterface> Transactions
    {
        get { return _transactions; }
        set
        {
            _transactions = value;
            OnPropertyChanged(() => Transactions);
        }
    }

Example of a class in the list public class WholesaleDialogTradeItemViewModel : ViewModelBase, ITestInterface { private string _tradeDirection; private string _book; private string _counterpart; private int _volume; private int _price; private string _product; private string _delivery; private string _period;

    public string TradeDirection
    {
        get { return _tradeDirection; }
        set
        {
            _tradeDirection = value; 
            OnPropertyChanged(() => TradeDirection);
        }
    }

    public string Book
    {
        get { return _book; }
        set
        {
            _book = value; 
            OnPropertyChanged(() => Book);
        }
    }

    public string Counterpart
    {
        get { return _counterpart; }
        set
        {
            _counterpart = value; 
            OnPropertyChanged(() => Counterpart);
        }
    }

    public string Product
    {
        get { return _product; }
        set { _product = value; OnPropertyChanged(() => Product); }
    }

    public string Delivery
    {
        get { return _delivery; }
        set { _delivery = value; OnPropertyChanged(()=> Delivery);}
    }

    public string Period
    {
        get { return _period; }
        set { _period = value; OnPropertyChanged(() => Period);}
    }

    public int Volume
    {
        get { return _volume; }
        set { _volume = value; OnPropertyChanged(() => Volume);}
    }

    public int Price
    {
        get { return _price; }
        set { _price = value; OnPropertyChanged(() => Price);}
    }
}

public interface ITestInterface
{
    string Counterpart { get; }
}

The XAML

   <Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <DataGrid
        Grid.Row="0"
        Width="600"
        SelectionMode="Extended"
        SelectionUnit="FullRow"
        CanUserDeleteRows="False"
        CanUserResizeRows="False"
        IsReadOnly="True"
        AutoGenerateColumns="True"
        AutoGeneratingColumn="DataGrid_OnAutoGeneratingColumn"
        ItemsSource="{Binding Transactions, Mode=OneWay}">

    </DataGrid>
    <Grid 
        Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Button 
            Grid.Column="0"
            Margin="5,10,5,0"
            cal:Click.Command="{Binding SaveCommand}"
            Height="25">
            <AccessText>_OK</AccessText>
        </Button>
        <Button 
            Grid.Column="1"
            Margin="5,10,5,0"
            cal:Click.Command="{Binding CancelCommand}"
            Height="25">
            <AccessText>_Cancel</AccessText>
        </Button>
    </Grid>
</Grid>

The result in this example is that I get the Counterpart string, but every other property from WholesaleDialogTradeItemViewModel is not displayed, if I remove Counterpart from the Interface nothing is shown

Another example (Right click on it to show full size) enter image description here

Upvotes: 1

Views: 298

Answers (1)

Mech0z
Mech0z

Reputation: 3647

The answer ended up with replacing

public ObservableCollection<ITestInterface> Transactions

with

public ObservableCollection<object> Transactions

Apparently that forces the compiler to use reflection to find out what to show, if I used the interface it would just take that

Upvotes: 0

Related Questions