0

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;
        }
    }
}
user3249586
  • 23
  • 1
  • 5
  • 1
    Observations: in your `MainWindow` you are not setting the `GraphicViewModel` property which would set the DataContext. Instead, you keep the viewmodel in Resources section and bind to it via StaticResource.. this is totally odd. Decide which way you waould like to use it: either it should be set as `window.DataContext` by code, or either it should be set as the DataContext by XAML (both are OK and mostly the same), or, if you want to keep in the Resources, then write the code appropriately and dont refer to DataContext at all (which will stay NULL that way) – quetzalcoatl Jun 09 '17 at 14:58
  • and regarding (2) no, it is not. Normal `{Binding}` markups in XAML are completely unrelated to DI. `{Binding}` only watches the Source (or DataContext if Source is not specified) and watches the Path (property.property.property.xxx) on that Source (DataContext). This is as simple as that. No interaction with DI container at all. – quetzalcoatl Jun 09 '17 at 14:59
  • Thanks. I would like to set DataContext directly to Xamdatagrid in XAML. Can I request you to paste the working/modified code here, as I have tried it also but didn't get success. Something I am doing wrong. – user3249586 Jun 09 '17 at 15:08
  • public MainWindow() { InitializeComponent(); **this.DataContext = new GraphicViewModel();** } As a quick fix but there are so many other ways to set the context. – Daniel Filipov Jun 09 '17 at 15:14
  • @Daniel Filipov , I tried below code, with empty grid & no error in output window: public MainWindow() { InitializeComponent(); GraphicViewModel obj = new GraphicViewModel(); ItemsSource.DataSource = obj.ItemsSource; } AND, ... – user3249586 Jun 09 '17 at 15:19
  • If you are binding to the property of your collection you should poind that using key word Binding. Checked="CheckBox_Checked" and hecked="{Binding CheckBox_Checked, Mode=TwoWay"} As if you need the value of Type then it should be Text="{Binding Type}" – Daniel Filipov Jun 09 '17 at 15:29
  • @Daniel Filipov, I simply would like to load the grid with data on windows startup, so did the binding in code behind constructor, as can be seen in my previous comment. But grid is still empty. What changes should I do here. – user3249586 Jun 09 '17 at 15:34
  • @user3249586 If you follow Rachel's answer(basically same as what i commented) and still can't get it working. To get the value of Type, Name, Width and so on ... just replace "Type" with "{Binding Type}" – Daniel Filipov Jun 09 '17 at 15:55

2 Answers2

0

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.

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Thank you for the clarification. What I understood from your explanation, tried to do those changes but still grid is empty. One thing to mention is that XamDataGrid does not have ItemsSource property rather has DataSource property, so I used it. My updated code is as below: public MainWindow() { InitializeComponent(); ItemsSource.DataContext= new GraphicViewModel(); } And, – user3249586 Jun 09 '17 at 16:14
  • @user3249586 I'd recommend downloading a tool like [WPF Snoop](https://snoopwpf.codeplex.com/) and looking at the DataContext during runtime to make sure it is correct. It sounds like perhaps it is not – Rachel Jun 09 '17 at 23:20
  • Small correction - opening words that `"create a property of type GraphicViewModel and name it dataContext"` - that's totally not true and totaly unlike that. You've probably thought about Component `x:Name` (which loosely be described in a similar way to what you wrote) but wrote it in context of Resource `x:Key` (which puts the thing into `window.Resources[key]` resource dictionary). Resource dictionaries are much more complex than that thanks to sharing, styles, themes and other whatchamacallits - although, here, in fact, none of it will probably not be visible at all. – quetzalcoatl Jun 10 '17 at 18:39
0

Thanks a lot @Rachel, @Daniel Filipov & @quetzalcoatl, I got my code working now. The changes done in below files:

MainWindow.xaml.cs

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

MainWindow.xaml:

 <igDP:XamDataGrid x:Name="ItemsSource" DataSource="{Binding ItemsSource, Mode=TwoWay}" .../>
user3249586
  • 23
  • 1
  • 5