user2475983
user2475983

Reputation: 2122

Pass values to ValueConverter from two different binding sources in single DataGrid

What I want to do is to color DataGridRow red if validation fails. I attempted to do so with ValueConverter but I have no idea how to pass value from more than one binding source.

I've got datagrid with binding to collection of objects. Then there's a DataGridTemplateColumn with ComboBox and Textbox inside (only one is visible at time), and the ComboBox has non related to bound collection binding source.

See code:

<DataGrid Grid.Row="4" Grid.Column="0" x:Name="DGR_Slots" Grid.ColumnSpan="5" Grid.RowSpan="3" ItemsSource="{Binding ElementName=WND_ItemCraftingWindow, Path=SelectedSchematic.Slots}" AutoGenerateColumns="False" ColumnWidth="*">
    <DataGrid.Resources>
        <classes:ValidationConverter x:Key="ValidationConverter" />
    </DataGrid.Resources>

    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="Background" Value="{Binding Converter={StaticResource ValidationConverter}}" />
        </Style>
    </DataGrid.RowStyle>

    <DataGrid.Columns>
        <DataGridTextColumn Header="Id" Binding="{Binding Id}" Visibility="Collapsed"/>
        <DataGridTextColumn Header="Slot Type" Binding="{Binding SlotType}" />
        <DataGridTextColumn Header="Mat Type" Binding="{Binding MaterialType}" />
        <DataGridTextColumn Header="Count" Binding="{Binding MaterialCount}" />
        <!--<DataGridComboBoxColumn Header="Material" />-->
        <DataGridTemplateColumn Header="Material">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <ComboBox Visibility="Visible"  MouseDoubleClick="MaterialCell_MouseDoubleClick" ItemsSource="{Binding ElementName=WND_ItemCraftingWindow, Path=Materials}" DisplayMemberPath="Name" SelectedValuePath="Name" SelectionChanged="MaterialComboBox_SelectionChanged"/>
                        <TextBox Visibility="Collapsed" MouseDoubleClick="MaterialCell_MouseDoubleClick" PreviewKeyUp="MaterialCell_TextBox_PreviewKeyUp" KeyUp="MaterialCell_TextBox_KeyUp" />
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

WND_ItemCraftingWindow is the Window that owns the datagrid and the Materials is ObservableCollection property inside that window.

I need to pass the object from DataGrid.ItemsSource collection (that works now) and SelectedItem from Combobox in same row (i dont know how to do that) into ValidationConverter.

Validation of the row can be performed only with the object from DataGridRow and SelectedItem from combobox.

Also I'm open to different solutions to color the row after such validation.

Upvotes: 0

Views: 359

Answers (1)

user2475983
user2475983

Reputation: 2122

Alright I managed to do it hackish way.

Datagrid code (removed meaningless parts):

<DataGrid x:Name="DGR_Slots" ItemsSource="{Binding ElementName=WND_ItemCraftingWindow, Path=SelectedSchematic.Slots}" AutoGenerateColumns="False" ColumnWidth="*" IsReadOnly="True">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Material">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <ComboBox Visibility="Visible" ItemsSource="{Binding ElementName=WND_ItemCraftingWindow, Path=Materials}" SelectionChanged="MaterialComboBox_SelectionChanged" />
                        <TextBox Visibility="Collapsed" />
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

SelectionChanged event

private void MaterialComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // ...

    var slot = (DGR_Slots.SelectedItem as SchematicSlot);
    var mat = ((sender as ComboBox).SelectedItem as Material);
    var row = WPFHelper.GetRow(DGR_Slots, DGR_Slots.SelectedIndex);

    row.Background = new SolidColorBrush(slot.MaterialType != mat.MaterialType ? Colors.Red : Colors.White);
}

WPFHelper GetRow method (found somewhere on the internet)

static public DataGridRow GetRow(DataGrid dg, int index)
{
    DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(index);

    if (row == null)
    {
        // may be virtualized, bring into view and try again
        dg.ScrollIntoView(dg.Items[index]);
        row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(index);
    }

    return row;
}

Although I'm still open to other solutions.

Upvotes: 0

Related Questions