wpfbindinginfragisticsdatacontextxamdatagrid

How to bind XamDataGrids available on different panels with different collections on a WPF page, using pure MVVM concepts & dependency injection.


I have a WPF XAML page, having 3 sections separated by DockPanels. One panel contains an INFRAGITICS XamDataGrid control to be bound with a collection.

  1. I would like to bind XamDataGrid control using DataContext/DataSource property in pure MVVM way.
  2. Also, would be delighted to understand if binding is done through dependency injection.

I have tried different approaches but didn't get success. I have pasted my code below for reference. Kindly help.

XAML Page:

<Window x:Class="UserInterface.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:UserInterface"
        xmlns:igDP="clr-namespace:Infragistics.Windows.DataPresenter;assembly=InfragisticsWPF.DataPresenter"
             xmlns:igEditors="clr-namespace:Infragistics.Windows.Editors;assembly=InfragisticsWPF.Editors"   
             xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        xmlns:dc ="clr-namespace:UserInterface.ViewModel"
         xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        mc:Ignorable="d"
        Title="MainWindow">
    <Window.Resources>
        <dc:GraphicViewModel x:Key="dataContext"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height=".5*"/>
            <RowDefinition Height=".5*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=".5*"/>
            <ColumnDefinition Width=".5*"/>
        </Grid.ColumnDefinitions>

        <DockPanel  Grid.Column="0" Grid.Row="0">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
            </Grid>
            <!--<StackPanel Orientation="Vertical" DockPanel.Dock="Top">
                <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="0">
                    <DockPanel>
                        <TextBlock Text="*.cfg File" Grid.Column="0" DockPanel.Dock="Left"/>
                        <Button Content="Browse..." Grid.Column="2" DockPanel.Dock="Right"/>
                        <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse *.cfg file..." Grid.Column="1" DockPanel.Dock="Right"/>
                    </DockPanel>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="1">
                    <TextBlock Text="*.ps File  " Grid.Column="0"/>
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse *.ps file..." Grid.Column="1"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="2">
                    <TextBlock Text="*.pic File " Grid.Column="0"/>
                    <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.pic file..." Grid.Column="1"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="3">
                    <TextBlock Text="*.xlsx File" Grid.Column="0"/>
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse *.xlsx file..." Grid.Column="1"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="4">
                    <TextBlock Text="*.xlsx File"/>
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse *.xlsx file..." Grid.Column="1"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                </StackPanel>
            </StackPanel>-->
            <StackPanel Orientation="Horizontal">
                <StackPanel Orientation="Vertical" Margin="5" Grid.Row="0">
                    <TextBlock MinHeight="20.5" Text="*.cfg File" Grid.Column="0"/>
                    <TextBlock MinHeight="20.5" Text="*.ps File  " Grid.Column="0"/>
                    <TextBlock MinHeight="20.5" Text="*.pic File " Grid.Column="0"/>
                    <TextBlock MinHeight="20.5" Text="*.xlsx File" Grid.Column="0"/>
                    <TextBlock MinHeight="20.5" Text="*.xlsx File"  Grid.Column="0"/>                   
                </StackPanel>
                <StackPanel Orientation="Vertical" Margin="5" Grid.Row="1">
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse *.cfg file..." Grid.Column="1" MinHeight="20.5"/>
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse *.ps file..." Grid.Column="1"  MinHeight="20.5"/>
                    <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.pic file..." Grid.Column="1"  MinHeight="20.5"/>
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse Model mapping file..." Grid.Column="1"  MinHeight="20.5"/>
                    <TextBox FontStyle="Italic" FontWeight="Light"  Text="Browse Parameter mapping file..." Grid.Column="1"  MinHeight="20.5"/>                   
                </StackPanel>
                <StackPanel Orientation="Vertical" Margin="5" Grid.Row="2">
                    <Button Content="Browse..." Grid.Column="2"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                    <Button Content="Browse..." Grid.Column="2"/>
                </StackPanel>               
            </StackPanel>
        </DockPanel>
        <DockPanel  Grid.Column="1" Grid.Row="0">
            <igDP:XamDataGrid x:Name="ItemsSource"  DataContext="{Binding Source={StaticResource dataContext}, Path=ItemsSource, Mode=TwoWay}" Grid.Row="0" Margin="10" AutoFit="true">
                <igDP:XamDataGrid.ViewSettings>
                    <igDP:GridViewSettings/>
                </igDP:XamDataGrid.ViewSettings>

                <igDP:XamDataGrid.FieldSettings>
                    <igDP:FieldSettings  LabelTextAlignment="Left" AllowRecordFiltering="true" FilterOperandUIType="ExcelStyle" FilterStringComparisonType="CaseInsensitive" FilterOperatorDefaultValue="Contains"
                                       LabelClickAction="SortByOneFieldOnlyTriState" SortComparisonType="Default"/>
                </igDP:XamDataGrid.FieldSettings>
                <igDP:XamDataGrid.FieldLayoutSettings>
                    <igDP:FieldLayoutSettings  DataErrorDisplayMode="ErrorIconAndHighlight" SupportDataErrorInfo="RecordsAndCells" SelectionTypeRecord ="Single"                                
                              AutoGenerateFields="False" FilterUIType="FilterRecord"/>
                </igDP:XamDataGrid.FieldLayoutSettings>
                <igDP:XamDataGrid.FieldLayouts>
                    <igDP:FieldLayout>
                        <igDP:FieldLayout.Fields>
                            <igDP:Field  Name="IsSelected" Label="Select" HorizontalContentAlignment="Left"  Width="Auto" VerticalContentAlignment="Center">
                                <igDP:Field.Settings>
                                    <igDP:FieldSettings DataItemUpdateTrigger="OnCellValueChange">
                                        <igDP:FieldSettings.LabelPresenterStyle>
                                            <Style TargetType="{x:Type igDP:LabelPresenter}">
                                                <Setter Property="ContentTemplate">
                                                    <Setter.Value>
                                                        <DataTemplate>
                                                            <CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" Content="" />
                                                        </DataTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </igDP:FieldSettings.LabelPresenterStyle>
                                    </igDP:FieldSettings>
                                </igDP:Field.Settings>
                            </igDP:Field>
                            <igDP:Field Label="Name" Name="Name" AllowEdit="False" HorizontalContentAlignment="Left" Width="Auto">                               
                            </igDP:Field>
                            <igDP:Field Label="Type" Name="Type" AllowEdit="False" HorizontalContentAlignment="Left" Width="*"/>
                            <igDP:Field Label="Background" Name="Background" AllowEdit="False" HorizontalContentAlignment="Left" Width="Auto"/>
                            <igDP:Field Label="Width" Name="Width" AllowEdit="False" HorizontalContentAlignment="Right" Width="Auto"/>
                            <igDP:Field Label="Height" Name="Height" AllowEdit="False" HorizontalContentAlignment="Right" Width="Auto"/>                            
                        </igDP:FieldLayout.Fields>
                    </igDP:FieldLayout>
                </igDP:XamDataGrid.FieldLayouts>
            </igDP:XamDataGrid>
        </DockPanel>
        <DockPanel Grid.Column="0" Grid.Row="1" Grid.RowSpan="2">
            <StackPanel Orientation="Vertical" DockPanel.Dock="Bottom">    
                <TextBox Text="Sample Text1"/>
                <TextBox Text="Sample Text2"/>    
                <TextBox Text="Sample Text3"/>
                <TextBox Text="Sample Text4"/>    
            </StackPanel>
        </DockPanel>
        <!--</StackPanel>-->
    </Grid>
</Window>

Xaml page code behind:

namespace UserInterface
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();                
            //GraphicViewModel obj = new GraphicViewModel();                
            //ItemsSource.DataSource = obj.ItemsSource;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion INotifyPropertyChanged Members
        public GraphicViewModel GraphicViewModel
        {
            get { return this.DataContext as GraphicViewModel; }
            set
            {
                this.DataContext = value;
                if (this.DataContext != null)
                    NotifyPropertyChanged("GraphicViewModel");
            }
        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {

        }

        private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
        {

        }
    }
}

Model Class:

namespace UserInterface.Model
{
    public class GraphicsModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void NotifyOfPropertyChange(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected == value) return;

                _isSelected = value;
                NotifyOfPropertyChange("IsSelected");
            }
        }

        private string _name = string.Empty;
        public string Name
        {
            get { return _name; }
            set
            {
                if (_name != value)
                    _name = value;
                NotifyOfPropertyChange("Name");
            }
        }

        private string _type = string.Empty;
        public string Type
        {
            get { return _type; }
            set
            {
                if (_type != value)
                    _type = value;
                NotifyOfPropertyChange("Type");
            }
        }

        private string _width = string.Empty;
        public string Width
        {
            get { return _width; }
            set
            {
                if (_width != value)
                    _width = value;
                NotifyOfPropertyChange("Width");
            }
        }

        private string _height = string.Empty;
        public string Height
        {
            get { return _height; }
            set
            {
                if (_height != value)
                    _height = value;
                NotifyOfPropertyChange("Height");
            }
        }
    }
}

ViewModel class:

namespace UserInterface.ViewModel
{
    public class GraphicViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void NotifyOfPropertyChange(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }

        private ObservableCollection<GraphicsModel> _itemsSource = new ObservableCollection<GraphicsModel>();


       // MainWindow _view = null;
        public ObservableCollection<GraphicsModel> ItemsSource
        {
            get { return _itemsSource; }
            set
            {
                if (_itemsSource == value) return;

                _itemsSource = value;
                NotifyOfPropertyChange("ItemsSource");
            }
        }

        public GraphicViewModel()
        {
            //_view = view;           
            _itemsSource = new ObservableCollection<GraphicsModel>() { new GraphicsModel() { Name = "sdasdad", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,
            new GraphicsModel() { Name = "sdsa", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "sdasdad", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "asas", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "rewwe", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,};            
            //view.GraphicViewModel = this;
        }
    }
}

Solution

  • When you write

    <Window.Resources>
        <dc:GraphicViewModel x:Key="dataContext"/>
    </Window.Resources>
    

    You are saying "create a property of type GraphicViewModel and name it dataContext". It's almost the exact same as doing something like this in the code-behind :

    private GraphicViewModel dataContext = new GraphicViewModel();
    

    When you write

    <igDP:XamDataGrid DataContext="{Binding Source={StaticResource dataContext}, Path=ItemsSource, Mode=TwoWay}" .. />
    

    You are saying "bind the igDP:XamDataGrid.DataContext property to dataContext.ItemsSource".

    Now for why the Grid won't load, the .DataContext property doesn't actually do anything. It's just a holder for the data that sits behind the control. So if you were to write

    <igDP:XamDataGrid ItemsSource="{Binding MyProperty}" />
    

    It would be to tell WPF "set XamDataGrid.ItemsSource property equal to XamDataGrid.DataContext.MyProperty".

    Since in the code above you set the DataContext equal to dataContext.ItemsSource, it would try to set the value to dataContext.ItemsSource.MyProperty (which of course does not exist).

    What you actually need is something like

    <igDP:XamDataGrid ItemsSource="{Binding Source={StaticResource dataContext}, Path=ItemsSource}" .. />
    

    This binds the .ItemsSource property of the grid (which is the property it builds its data rows from) to the static resource created in <Window.Resources> named "dataContext", and the property on that object called ItemsSource.

    Second issue here though is you seem to have multiple copies of your ViewModel in your code. Personally I recommend never creating objects in the XAML like you did for your GraphicViewModel. Instead, I would recommend something like this :

    public MainWindow()
    {
        InitializeComponent();                
        this.DataContext = new GraphicViewModel();
    }
    

    Now it should be noted that this creates a new instance of the GraphicViewModel, but doesn't store it anywhere. If you want to access this object in other code-behind without casting this.DataContext to GraphicViewModel, then you should probably store the value somewhere.

    Once the Window.DataContext is set, you can write the bindings without specifying a custom Source property for the binding.

    <igDP:XamDataGrid ItemsSource="{Binding ItemsSource}" .. />
    

    This will work because WPF controls will look up the DataContext from their parent by default if it is not specifically set. So in this case, the .DataContext property for XamDataGrid is null so it will travel up the visual tree looking for something with a DataContext until it runs into Window.DataContext which you've set in the constructor to a new instance of your GraphicViewModel.

    For people looking to understand the DataContext property, I usually send them to this SO answer to avoid having to retype the same thing all the time. I'd recommend reading it if you're still working to understand what the DataContext is or how it's used.

    Also that said, Dependency Injection is something different and wouldn't be used here at all.