Home > Blockchain >  How do I get a certain row within a wpf datagrid, which is formed by DataGridTextColumns?
How do I get a certain row within a wpf datagrid, which is formed by DataGridTextColumns?

Time:01-17

I got a datagrid of 3 rows.The datagrid is generated by a class which writes three columns a time.
This process performs 3 times so that'a 9-cell datagrid.
Please noted that it's formed by columns.
And I have a combobox of 3 comboboxItem.
The combobox_SelectionChanged method is set like this:

private void ComboInput_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ComboOpticalInput.SelectedIndex == 2)
// 1st row of the datagrid is invisible or grayish      
sentense 1;
    else if (ComboOpticalInput.SelectedIndex == 1)
    // 2nd row of the datagrid is invisible or grayish 
    sentense 2;
       else
       // 3rd row of the datagrid is invisible or grayish 
       sentense 3;
}

And my datarid is like:

<DataGrid Name="DataGrid1" >
  <DataGrid.Columns>
    <DataGridTextColumn Header="Parameter" Binding="{Binding Option}" x:Name="DGOP1" />
    <DataGridTextColumn Header="Value1" Binding="{Binding Pvalue}" x:Name="DGOP2" /> 
    <DataGridTextColumn Header="Value2" Binding="{Binding Qvalue}" x:Name="DGOP3" /> 
   </DataGrid.Columns>
</DataGrid>

My Question is : How do i write sentense 1? I searched for quite some time didn't find a solution.

Or should I generated the datagrid in other ways? Or should I get to row1 by selecting first 3 columns of row1?

I googled this, many of the answers are about selected datagrid rows.

I don't need to select any of the row.The interact within comboboxItem selection and one row of the datagrid is set.

Also I tried:

```DataGrid1.row[1].Visibility = Visibility.Collapsed;```

and the return is:

>"datagrid" does not contain a definition for "row"

CodePudding user response:

My Question is : How do i write sentense 1?

You don't. What I've learned about WPF is to stay away from writing code in favour of using bindings and other mechanisms that WPF provides.

To solve your problem you can basically do, what I've described in another thread here: How to use a xaml control to show/hide other controls?

In your case you can perhaps modify the ValueConverter to return Visibility instead of bool. Make sure you name your ComboBox and then, when generating your DataGrid rows, you add binding to each row's Visibility property in a similar way that I've described for the IsEnabled of the Labels.

CodePudding user response:

When they were designing WPF they took some fundamental design choices.

One design choice was to favour binding over the VB6 pattern devs used of building controls and adding them into comboboxes or gridviews.

It is not particularly obvious how you get at a row out a datagrid in code. The designers did not envision that to be the way devs would work with rows.

You could do this in code:

    private void ComboInput_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (lastRowIndex > -1)
        {
            var lastrow = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(lastRowIndex);
            lastrow.IsEnabled = true;
        }

        var row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(ComboInput.SelectedIndex);
        row.IsEnabled = false;
        lastRowIndex = ComboInput.SelectedIndex;
    }
    int lastRowIndex = -1;

Here my datagrid is called dg ( obviously ).

This approach relies on the selected index of the combobox being the same as the index of the row in the datagrid you want to gray. I am just using IsEnabled here but you could do other things with that row once you have a reference if you prefer.

You could use a binding and converter usually to set a value on some property. You need both the index of the row considered and the value of whatever is set in the combobox. You'd need a multibinding and multiconverter.

It would also be good if this multiconverter was at least somewhat re-usable.

We also need some way to get at that row, which would be to use rowstyle.

Bringing all that together my xaml would look like:

    <DataGrid Name="dg" AutoGenerateColumns="False"
              AlternationCount="10000">
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Setter Property="IsEnabled">
                    <Setter.Value>
                        <MultiBinding Converter="{local:IsMultiNotEqualConverter}">
                            <Binding Path="AlternationIndex" RelativeSource="{RelativeSource Self}"/>
                            <Binding Path="SelectedIndex" ElementName="ComboInput"/>
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.RowStyle>

Alternationindex is being used here to give the row index.

The multiconverter looks like:

public class IsMultiNotEqualConverter : MarkupExtension, IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !values[0].Equals(values[1]);
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return null;
    }
    private static IsMultiNotEqualConverter _converter = null;
    public override object ProvideValue(IServiceProvider serviceProvider) => _converter ??= new IsMultiNotEqualConverter();
}

Which can be used without declaring it as a resource because it's a markupextension as well as a converter.

That multi binding and converter could instead be used in a datatrigger to apply a style to your particular row.

This isn't super complicated but it's also not super simple and you can perhaps see why it's more usual to work with bound collections of viewmodels which can have logic encapsulated in code within them and bind properties directly to them.

  • Related