Search code examples
c#xamluwpdatagriddatagridtemplatecolumn

How do I bind a comboBox to a different ItemsSource than it's parent DataGrid's ItemSource in a UWP project?


I am using MVVM and bind a DataGrid to an ObservableCollection<CustomClass>. I can successfully do that, however I want one of the DataGrid columns to be a ComboBox column, with items source List<ComboBoxValues>. Also another column must be a ToggleSwitch where a Command with parameter is fired when it's IsOn property changes value.

In the ViewModel:

    public ObservableCollection<CustomClass> DataGridData { get; set; } = new ObservableCollection<CustomClass>();
    public List<ComboBoxValues> ListValues { get; set; } = new List<ComboBoxValues>();
    public MyICommand<ToggleSwitch> ToggleSwitchToggled_Command { get; private set; }

The problem I am getting is that the DataGrid's ItemsSource Binding is overriding the Binding path for the CombobBox's ItemsSource, as well as the Command's Binding. ListValues and ToggleSwitchToggled_Command is looked for within DataGridData.

For example:

Error: BindingExpression path error: 'ListValues' property not found on 'UWPProject.ViewModels.DataGridData'. BindingExpression: Path='ListValues' DataItem='UWPProject.ViewModels.DataGridData'; target element is 'Windows.UI.Xaml.Controls.ComboBox' (Name='null'); target property is 'ItemsSource' (type 'Object')

In Xaml:

      <controls:DataGrid GridLinesVisibility="All"
                         AlternatingRowBackground="Gray" AutoGenerateColumns="False"
                         ItemsSource="{Binding DataGridData,Mode=TwoWay}">
            <controls:DataGrid.Columns>
                <controls:DataGridTextColumn Header="TextOne" Binding="{Binding aPropertyOneInDataGridData,Mode=TwoWay}"/>
                <controls:DataGridTextColumn Header="TextTwo" Binding="{Binding aPropertyTwoInDataGridData,Mode=TwoWay}"/>
                <controls:DataGridTemplateColumn Header="ComboBoxHeader">
                    <controls:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                                <ComboBox ItemsSource="{Binding ListValues}"
                                          SelectedValue="{Binding aPropertyThreeInDataGridData,Mode=TwoWay}"
                                          PlaceholderText="Select Action">
                                </ComboBox>
                            </StackPanel>
                        </DataTemplate>
                    </controls:DataGridTemplateColumn.CellTemplate>
                </controls:DataGridTemplateColumn>
                <controls:DataGridTemplateColumn Header="ToggleSwitch_Header">
                    <controls:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                                <ToggleSwitch x:Name="ToggelSwitch_Run"
                                              IsOn="{Binding aPropertyFourInDataGridData,Mode=TwoWay}">
                                    <interact:Interaction.Behaviors>
                                        <interactcore:EventTriggerBehavior EventName="Toggled">
                                            <interactcore:InvokeCommandAction Command="{Binding ToggleSwitchToggled_Command}"
                                                                              CommandParameter="{Binding}"/>
                                        </interactcore:EventTriggerBehavior>
                                    </interact:Interaction.Behaviors>
                                </ToggleSwitch>
                            </StackPanel>
                        </DataTemplate>
                    </controls:DataGridTemplateColumn.CellTemplate>
                </controls:DataGridTemplateColumn>
            </controls:DataGrid.Columns>
        </controls:DataGrid>

So I guess, the question is, how do I split the "source" or path where the Binding is looked for within the parent DataGrid. There are many WPF questions and answers on this, such as here and here. however I can't use DataContext, as I get the error that "DataContext is not supported in a UWP project." I can't find a solution for a UWP project for this problem. Also, I am using MVVM and no code behind, so I don't believe I can use x:Binding. I don't want to use code behind either.

Please help.


Solution

  • For your scenario, we suggest use DataGridComboBoxColumn to replace custom celltemplate. Then you could use x:bind markup extension to bind list property directly. Because DataGridComboBoxColumn ItemsSource property could not access data source sub property directly, If you already make ListValues property for the Page class, you could also use x:bind to access like the following.

    <controls:DataGridComboBoxColumn 
        Width="*"
        Binding="{Binding p2}"
        Header="Link"   
        ItemsSource="{x:Bind ListValues ,Mode=OneWay}"
        Tag="Link"
        />
    

    If you do want to make custom celltemplate, you could insert the ListValues property into your CustomClass. For more detail please refer this case reply.