WPF hide row in datagrid based on condition

2019-04-04 06:22发布

问题:

I need to hide rows in datagrid based on parameters and values in the datagrid. I figured to do something like this;

foreach (System.Data.DataRowView dr in myDataGrid.ItemsSource)
{
   //Logic to determine if Row should be hidden
   if (hideRow == "Yes")
   {
      //Hide row code
   }
}

I just cannot figure how to actual hide the row. Please note I don't want to remove the row form the datagrid or the item source.

回答1:

If hideRow is not a field of the table (i.e. not a column in the DataGridRow):

<DataGrid.RowStyle>
    <Style TargetType="{x:Type DataGridRow}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding AnyProp, Converter={StaticResource hiddenConverter}}" Value="True">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</DataGrid.RowStyle>

And realize Converter with your logic. The type of the bound variable, AnyProp above, will be yourPropertyType below. AnyProp could be any of the columns in the row.

[ValueConversion(typeof(yourPropType), typeof(bool))]
public class hiddenConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (hideRow == "Yes")
        {
           return true;
        }
        else
        {
           return false;
        }
    }


}

'value' will be AnyProp, and it can be used in the logic that determines whether or not to show the row, or that decision can be based on something else entirely, such as 'hideRow' in the example.



回答2:

You can do this in Datagrid.ItemContainerStyle instead of doing it in codebehind...

  <DataGrid>
      <DataGrid.ItemContainerStyle>
            <Style TargetType="DataGridRow">
                 <Style.Triggers>
                       <DataTrigger Binding="{Binding PROPERTY}"  Value="VALUE">
                              <Setter Property="Visibility" Value="Collapsed"/>


回答3:

Use a CollectionViewSource to link the DataGrid with your business data. The CollectionViewSource fires a filter event for every row. In this event, your code can decide if the row should be displayed.

Add to your XAML:

<Window.Resources>
  <CollectionViewSource x:Key="sampleViewSource" CollectionViewType="ListCollectionView"/>
</Window.Resources>

<DataGrid DataContext="{StaticResource sampleViewSource}" ItemsSource="{Binding}"
            AutoGenerateColumns="False">

Add the following to your code behind file:

stocksViewSource = ((System.Windows.Data.CollectionViewSource)(FindResource("sampleViewSource")));
sampleViewSource.Filter += sampleViewSource_Filter;

Create the filter eventhandler. You can get the row data from e.Item. By setting e.Accepted you can control if the row should be displayed.



回答4:

<Window x:Class="ProjectName.ClassName"
        xmlns:C="clr-namespace:ProjectName.FolderName"> //Folder containing 'VisibilitySetter' class.
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

  <Window.Resources>
    <C:VisibilitySetter x:Key="VisibilitySetter" />
  </Window.Resources>

  <DataGrid ItemsSource="{Binding SomeObservableCollectionProperty}">
    <DataGrid.RowStyle>
      <Style TargetType="DataGridRow">
        <Setter Property="Visibility" Value="{Binding Path=., Converter={StaticResource VisibilitySetter}, ConverterParameter=1}" />
      </Style>
    </DataGrid.RowStyle>

    </DataGridTextColumn>
      <DataGridTextColumn Binding="{Binding PropertyName1}" />
      <DataGridTextColumn Binding="{Binding PropertyName2}" />
      //................
  </DataGrid>
</Window >

VisibilitySetter is a Class that Implements IValueConverter. Here is the Class...

public class VisibilitySetter:IValueConverter 
{
  public object Convert(object value,Type targetType,object parameter,CultureInfo culture)
  {
    if(parameter.ToString() == "1")  //Parameter is set in the xaml file.
    {
      return SetVisibilityBasedOn(value);
    }
    return null;
  }

  private object SetVisibilityBasedOn(object value)
  {
    if(value is SomeObject obj && obj.value == "SomeValue") //Checks the value of the object
    {        
      return Visibility.Collapsed;  //Hides the row. It Returns visibility based on the value of the row.
    }
    return null;
  }
}