0

このコードを使用してセルの一部を強調表示できるように、DataGrid のセルを反復処理したい:

//Loop through all rows.
for (int x = 0; x < yourGridName.Rows.Count; x++) {
  //Loop through all cells in that row and change its color.
  for (int y = 0; y < yourGridName.Rows[x].Cells.Count; y++) {
    yourGridName.Rows[x].Cells[y].Style.BackColor = System.Drawing.Color.Red;
  }
}

次のように、WPF で DataGrid を定義しました。

<DataGrid AutoGenerateColumns="False"
  EnableRowVirtualization="True" ItemsSource="{Binding}"
  Margin="12,236,12,0" Name="conflictedDevicesDataGrid"
  RowDetailsVisibilityMode="VisibleWhenSelected" Grid.ColumnSpan="2"
  AlternatingRowBackground="#2FFF0000" IsManipulationEnabled="False">
  <DataGrid.Columns>
        ....
  </DataGrid.Columns>
</DataGrid>

次に、次のコードを入力しました。

var conflictedDevicesDataTable = new DataTable();
conflictedDevicesDataTable.Rows.Add(new object[] {
  "CSV",roc.scadaNode, roc.deviceName, roc.deviceDescription, roc.rocChannel,
  roc.rocAddress, roc.rocGroup, roc.configuration, roc.revision
});
...
conflictedDevicesDataGrid.ItemsSource = conflictedDevicesDataTable.DefaultView;

ただし、次の方法で列と行を反復しようとすると:

conflictedDevicesDataGrid.Rows[x]

行はアイテムではありません。列は反復できますが、行は反復できません。Google で見つけたすべての例では、.Rows[x] を介してデータグリッドを反復処理するように指示されていますが、これを実行できないようです。DataGrid の各セルを繰り返し処理し、プログラムで背景色を変更するにはどうすればよいですか?

4

1 に答える 1

1

さて、あなたが達成しようとしていることは、何らかの理由でWPFで実際にはかなり難しいです.

あなたが発見したように、WPFでは、特定の行のセルを反復処理することはできません。したがって、2 つのオプションがあります。

  • VisualTree のセルを反復処理します。第一に、仮想化を使用している場合、非常にひどく混乱するため、このオプションは強く思いとどまらせます。第二に、非常に醜いです。

  • viewModel に特別なプロパティを設定し、DataGrid.CellStyle を通じて dataGridCell の background プロパティをこれにバインドします。ここでの問題は、DataGridCell の datacontext が、セルが属する行に対応する ViewModel であり (図を参照)、セルによって表されるアイテムのプロパティではないため、直接バインドできないことです。「推移的な」入札を行う必要があるため、非常に複雑になります。

ここをご覧になることをお勧めします:

セル オブジェクトのプロパティを WPF DataGrid の DataGridCell にバインドする

そしてここ:

WPF DataGridCell を動的にスタイルする方法

この2番目のリンクは、あなたが達成したいのとまったく同じことを私がどのように行っているかを説明しています.

このようにして、アイテムを反復処理し、ViewModel でプロパティ値を設定できます。

編集:ここにあなたのためのコードがあります(あなたの質問に基づいて)

    <local:CellViewModelToTagConverter x:Key="CellViewModelToTagConverter" />

    <DataGrid AutoGenerateColumns="False"
              EnableRowVirtualization="True"
              ItemsSource="{Binding}"
              Margin="12,236,12,0"
              Name="conflictedDevicesDataGrid"
              RowDetailsVisibilityMode="VisibleWhenSelected"
              Grid.ColumnSpan="2"
              AlternatingRowBackground="#2FFF0000"
              IsManipulationEnabled="False">
        <DataGrid.Columns>
            <!--binding to the Text property of the CellViewModel for the column n°0-->
            <DataGridTextColumn Binding="{Binding [0].Text}">
                <DataGridTextColumn.CellStyle>
                    <Style TargetType="DataGridCell">
                        <!--this part is the most important, this is where you transfer the right dataContext to the cell-->
                        <Setter Property="Tag">
                            <Setter.Value>
                                <MultiBinding Converter="{StaticResource CellViewModelToTagConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
                                    <Binding />
                                    <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                        <!--and here, you bind the Background property-->
                        <Setter Property="Background" Value="{Binding Tag.Background, RelativeSource={RelativeSource Self}, Mode=OneWay}" />
                    </Style>
                </DataGridTextColumn.CellStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>

コンバーターのコードビハインドは次のとおりです。

public class CellViewModelToTagConverter : MarkupExtension, IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var row = values[0] as MyRowViewModel;
        var cell = values[1] as DataGridCell;

        if (row != null && cell != null)
        {
            var column = cell.Column as DataGridColumn;

            if (column != null)
                cell.SetBinding(FrameworkElement.TagProperty, new Binding {
                    Source = row[column.DataGridOwner.Columns.IndexOf(column)],
                    BindsDirectlyToSource = true
                });
        }

        return DependencyProperty.UnsetValue;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return new CellViewModelToTagConverter();
    }
}

もちろん、これはどこかにMyRowViewModelがあることを意味します:

internal class MyRowViewModel : Collection<MyCellViewModel>, INotifyPropertyChanged
{
}

および背景の依存関係プロパティを持つMyCellViewModel :

internal class MyCellViewModel : DependencyObject
{
private static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(Brush), typeof(MyCellViewModel));
internal Brush Background
{
    get { return (Brush)(GetValue(BackgroundProperty)); }
    set { SetValue(BackgroundProperty, value); }
}
}

これでうまくいくはずです(何も忘れていないことを願っています。忘れていたら、いつでもコメントを追加できます)

注意: もちろん、これは私のコードをわずかに変更したバージョンです。私のアプリははるかに複雑であり、このようにテストしていないため、いくつかの調整が必要になる場合があります。また、Foreground、Font、FontSyle、fontWeight などのプロパティも動的に設定するため、私の場合はセルのタイプごとに CellViewModel を用意する必要があります (ちなみに私のパフォーマンスの問題はそのためです)。よりシンプルな構造に。アイデアを自分のケースに適応させるだけです。

于 2012-07-18T09:58:13.777 に答える