Click here to Skip to main content
15,847,653 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have an XML which has some music info in it. I'm reading my XML to DataSet through ReadXml method. Then creating a DataTable and getting the 1st table info of DataSet and I'm trying to bind DataTable to DataGrid in MVVM Pattern. Below is my MainWindow View: Binding my ViewModel to MainWindow DataContext

XML
<Grid>
        <View:XElementV/>
        <View:XElementV DataContext="{Binding XElementVM}"/>
    </Grid>


MainWindow.Xaml.cs : Assigning VM as datacontext
C#
public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new XElementVM();
        }  


XElementV.Xaml :
XML
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <DataGrid ItemsSource="{Binding Path=DataTableObject, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="True"  CanUserAddRows="True" CanUserDeleteRows="False" IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="25">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <RadioButton HorizontalAlignment="Center" GroupName="Trail"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>    
        </DataGrid>
        <Button Grid.Row="1" VerticalAlignment="Center" Height="20" Content="Sample Button" HorizontalAlignment="Right" Margin="0,0,20,0"/>
    </Grid>


XElementVM.cs

C#
public XElementVM()
        {
            XmlTextReader xmlContent = new XmlTextReader(@"Music.xml");
            DataSet tableSet = new DataSet();
            tableSet.ReadXml(xmlContent);
            DataTableObject = tableSet.Tables[0];            
        }  

C#
When debugged the code, I'm able to get the XML data into the datatable but I'm unable to bind the data to UI. What might be the problem. Thank you.


Edit : Xml
XML
<Music>
  <Album Title="Chris Sells Live" Artist="Chris Sells" ReleaseDate="2/5/2008" /> 
  <Album Title="The Road to Redmond" Artist="Luka Abrus" ReleaseDate="4/3/2008" /> 
  <Album Title="The Best of Jim Hance" Artist="Jim Hance" ReleaseDate="6/2/2008" /> 
</Music>


What I have tried:

What ever the code which I have posted above is what I have tried.
Posted
Updated 8-Jun-16 1:00am
v3
Comments
VR Karthikeyan 8-Jun-16 3:59am    
show your xml file.
partha143 8-Jun-16 4:25am    
I have added the xml in edit part of the question. Kindly have a look at it.
VR Karthikeyan 8-Jun-16 5:12am    
Ok partha, but you are declared DataGrid with one checkbox column, but you have 3 columns in xml. So how do you want to show this in datagrid? do you wants to show all columns in datagrid?
partha143 8-Jun-16 5:28am    
Yes Karthik. I want RadioButton column to display 1st followed by Title, Artist and Releasedate.
VR Karthikeyan 8-Jun-16 6:01am    
Check the solution.

1 solution

Hi, refer the below function, it adds DataGridTextColumn dyn
C#
private void SetColumnsAndBinding(DataTable objTable)
{
    DataGridTemplateColumn objRadioButtonColumn = new DataGridTemplateColumn();
    DataTemplate RadioButtonCellTemplate = new DataTemplate();

    FrameworkElementFactory objRadButtonColumnFactory = new FrameworkElementFactory(typeof(RadioButton));
    objRadioButtonColumn.SetValue(RadioButton.GroupNameProperty, "Trial");
    RadioButtonCellTemplate.VisualTree = objRadButtonColumnFactory;
    objRadioButtonColumn.CellTemplate = RadioButtonCellTemplate;

    YourDataGrid.Columns.Add(objRadioButtonColumn);

    foreach (DataColumn objColumn in objTable.Columns)
    {
        DataGridTextColumn objDgridColumn = new DataGridTextColumn();
        objDgridColumn.Header = objColumn.ColumnName;

        Binding objBinding = new Binding();
        objBinding.Path = new PropertyPath(objColumn.ColumnName);

        objDgridColumn.Binding = objBinding;

        YourDataGrid.Columns.Add(objDgridColumn);
    }
}

This function adds a DataGridTemplateColumn in datagrid to show radiobutton. And it adds DataGridTextColumn objects based on the columns present in the DataTable, which is read from XML file. This is working. But it violates MVVM principle. In order to use this technique in MVVM, I did the following,
1. Declaring an ObservableCollection of DataGridColumn in the ViewModel to hold the columns collection, like this,
C#
private ObservableCollection<DataGridColumn> _CustomColumns = new ObservableCollection<DataGridColumn>();

public ObservableCollection<DataGridColumn> CustomColumns
{
    get { return _CustomColumns; }
    set
    {
        _CustomColumns = value;
        OnPropertyChanged("CustomColumns");
    }
}

By just modifying the above function, I can add columns to above collection like this,
C#
private void SetColumnsAndBinding(DataTable objTable)
{
    DataGridTemplateColumn objRadioButtonColumn = new DataGridTemplateColumn();
    DataTemplate RadioButtonCellTemplate = new DataTemplate();

    FrameworkElementFactory objRadButtonColumnFactory = new FrameworkElementFactory(typeof(RadioButton));
    objRadioButtonColumn.SetValue(RadioButton.GroupNameProperty, "Trial");
    RadioButtonCellTemplate.VisualTree = objRadButtonColumnFactory;
    objRadioButtonColumn.CellTemplate = RadioButtonCellTemplate;

    YourViewModel.CustomColumns.Add(objRadioButtonColumn);

    foreach (DataColumn objColumn in objTable.Columns)
    {
        DataGridTextColumn objDgridColumn = new DataGridTextColumn();
        objDgridColumn.Header = objColumn.ColumnName;

        Binding objBinding = new Binding();
        objBinding.Path = new PropertyPath(objColumn.ColumnName);

        objDgridColumn.Binding = objBinding;

        YourViewModel.CustomColumns.Add(objDgridColumn);
    }
}

Now, we have to bind this ObservableCollection of DataGridColumns to the datagrid. In this point, I cannot bind this collection to DataGrid's Columns property. For that I have referred the solution from StackOverflow link below,

c# - How do I bind a WPF DataGrid to a variable number of columns? - Stack Overflow[^]

According to this StackOverflow solution, I just added DataGridColumnsBehavior class in my solution. And changed DataGrid xaml like below,
XML
<DataGrid x:Name="MyDataGrid" HorizontalAlignment="Left" VerticalAlignment="Top"  ItemsSource="{Binding myTable}" AutoGenerateColumns="False" local:DataGridColumnsBehavior.BindableColumns="{Binding CustomColumns}" />

Use this.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900