0

I have a table called groups as shown below :

enter image description here

After looking at the image above I think you might have understood that primary key and foreign key exist in the same table. I think this is what developers call cyclic reference.

In MainWindow.xaml I have a DataGrid which contains three columns namely Group Name, Parent Name, Description. The xaml looks like :

<Window .......>

    <Window.DataContext>
        <self:MainWindowViewModel />
    </Window.DataContext>

    <DataGrid ItemsSource="{Binding Groups}" TabIndex="1">

        <DataGrid.Columns>

            <DataGridTemplateColumn Header="Group Name" Width="2*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding GroupName}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding GroupName}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Parent" Width="2*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding ParentID}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                  SelectedValue="{Binding ParentID}"
                                  DisplayMemberPath="GroupName"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Description" Width="2*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Description}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Description}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>

        </power:PowerDataGrid.Columns>

    </power:PowerDataGrid>

</Window>

Now I have a ViewModel called MainWindowViewModel

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel()
    {
        SampleDBContext sampleDBContext = new SampleDBContext();
        Groups = new ObservableCollection<Group>();
        GroupsCollection = new ObservableCollection<Group>(from g in sampleDBContext.Groups select g);
    }

    private ObservableCollection<Group> _groups;
    public ObservableCollection<Group> Groups
    {
        get
        {
            return _groups;
        }
        set
        {
            _groups = value;
            OnPropertyChanged("Groups");
        }
    }

    private ObservableCollection<Group> _groupsCollection;
    public ObservableCollection<Group> GroupsCollection
    {
        get
        {
            return _groupsCollection;
        }
        set
        {
            _groupsCollection = value;
            OnPropertyChanged("GroupsCollection");
        }
    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertryName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertryName));
        }
    }

    #endregion
}

Problems :

Output :

enter image description here

As you can see in the above image when I press TAB or Enter after selecting a group in Parent Column the next cell is focused but cell Under Parent Column has a red Outline indicating some error. Also cell does not leave edit mode. Also I get lot of binding errors in output window. So, I know that my binding is incorrect. Can somebody help me to bind Combobox inside a datagrid?

Update:

If I use the SelectedValuePath as below :

<ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
          SelectedValue="{Binding ParentID}" SelectedValuePath="{Binding GroupID}"
          DisplayMemberPath="GroupName" />

Then the error goes away and cell also leaves edit mode. But then TextBlock(which is celltemplate) always remains empty.

Vishal
  • 6,238
  • 10
  • 82
  • 158

1 Answers1

1

Solved it. I should not use Binding in SelectedValuePath. So, now my code should look something like :

<ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
          SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID"
          DisplayMemberPath="GroupName" />

Now problem is :

I get ID (but I want to have name instead of ID) of the SelectedValue of ComboBox after the edit mode is finished due to my binding of CellTemplate as below:

<DataGridTemplateColumn Header="Parent" Width="2*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ParentID}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding DataContext.GroupsCollection, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                      SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID"
                      DisplayMemberPath="GroupName" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

So I created a converter as below :

public class GroupIDToGroupName : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            SampleDBContext sampleDBContext = new SampleDBContext();
            return (from g in sampleDBContext.Groups
                    where g.GroupID == (int)value
                    select g.GroupName).FirstOrDefault();
        }
        else
        {
            return "";
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        SampleDBContext sampleDBContext = new SampleDBContext();
        return (from g in sampleDBContext.Groups
                where g.GroupName == (string)value
                select g.GroupID).FirstOrDefault();
    }
}

And I declared that converter in App.xaml as :

<self:GroupIDToGroupName x:Key="GroupIDToGroupNameConveerter" />

Now, my Cell template looks like :

<TextBlock Text="{Binding ParentID, Converter={StaticResource GroupIDToGroupNameConveerter}}" />

I don't know that I have solved my problem in the right way or not. But its working!!!!

If anybody has a good idea then please share...........

Vishal
  • 6,238
  • 10
  • 82
  • 158