如何在WPF DataGrid中突出显示行并强制行/单元格刷新?

时间:2012-03-15 16:50:37

标签: c# .net wpf datagrid wpf-controls

这是我关于SOF的第一个问题,所以请温柔地对待我:)

我在XAML中定义了一个简单的WPF DataGrid。应用程序从文本文件中将“用户”数据(FirstName,LastName)加载到网格中,并在从文本文件加载条目后,用户点击提交按钮,我想迭代列表中的项目并提交每个排到创建用户的Web服务,然后在网格中显示来自Web服务的回复。

为了让用户知情,我想以某种方式突出显示当前正在提交的行,并且我希望在收到回复后立即显示该消息。如果消息是错误,请以红色突出显示该行,如果成功,则将其突出显示为绿色。

看起来很简单......

我有一个简单的GridDto类,它表示要映射到每一行的数据。它实现了INotifyPropertyChanged接口。为简单起见,我将其定义如下:

class GridDto : INotifyPropertyChanged
{
  public string FirstName { get; set; }
  public string LastName { get; set; }

  private string Reply;
  public string Reply
  {
      get
      {
        return this.message;
      }
      set
      {
          this.message = value;
          this.PropertyChanged(this, new PropertyChangedEventArgs("Reply"));
      }
   }

网格接受文本文件中的FirstName和LastNames列表。

我填充此网格的方法是构建一个ObservableCollection<GridDto>的集合,然后我这样做:

resultGrid.ItemsSource = ConvertTextDtoToGridDtos(result.Elements);

到目前为止一切顺利。现在我想将网格的每一行提交给创建用户的Web服务。 websrvice需要的唯一参数是FirstName和LastName。

由于我是WPF的新手,我不知道如何做到这一点。这是我到目前为止所做的:

for (int i = 0; i < resultGrid.Items.Count - 1; i++)
{
    var dto = (GridDto)this.resultGrid.Items[i];
    var color = Color.FromRgb(192, 192, 25);
    try{
       // Do webservice call using the dto data
    }
    catch(Exception ex){
      dto.Reply = ex.Message;
      color = Color.FromRgb(255, 0, 0);
    }

  DataGridRow row = (DataGridRow)resultGrid.ItemContainerGenerator.ContainerFromIndex(i);
  row.Background = new SolidColorBrush(color) { Opacity = 0.45 };
}

这有点奏效,但不会突出显示当前正在处理的行。

我尝试在循环中添加以下内容

resultGrid.SelectedIndex = i;

或者...

resultGrid.SelectedItem = resultGrid.Items[i];
resultGrid.ScrollIntoView(resultGrid.Items[i]);

当循环结束时,只有最后一行突出显示。

此代码的另一个问题是,只有在提交了所有行之后,“回复”列才会在结尾处刷新,因此没有实时通知用户。

如何以智能方式突出显示当前处理的行,最重要的是,如何在每次回复后以及处理下一行之前更新回复单元格。

感谢您的帮助,对不起我的长期问题感到抱歉。

编辑:如果有更好的方式一起完成这项工作,我会获得建议。

2 个答案:

答案 0 :(得分:2)

首先,您可以将此代码绑定到DataGrid块中的XAML

,从而将bacgroundcolor绑定到样式中的属性
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Setter Property="Background" Value="{Binding Path=Color}"/>
            </Style>
        </DataGrid.RowStyle>

如果您想实时刷新UI,则必须使用backgroud worker来提交用户

            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += delegate(object s, DoWorkEventArgs we)
            {
                for (int i = 0; i < resultGrid.Items.Count - 1; i++)
                {
                    var dto = (GridDto)this.resultGrid.Items[i];
                    var color = Color.FromRgb(192, 192, 25);
                    try
                    {
                        // Do webservice call using the dto data
                    }
                    catch (Exception ex)
                    {
                        dto.Reply = ex.Message;
                        color = Color.FromRgb(255, 0, 0);
                    }
                    dto.Color = new SolidColorBrush(color) { Opacity = 0.45 };
                }
            };
            bw.RunWorkerAsync();

答案 1 :(得分:0)

这可能是一个选择:

将以下内容添加到GridDto

private Brush validationBrush = Brushes.White;

public Brush ValidationBrush
{
  get { return validationBrush; }
  set
  {
    validationBrush = value;
     this.PropertyChanged(this, new PropertyChangedEventArgs("ValidationBrush"));
  }
}

这是在Xaml的DataGrid标签中

  <DataGrid.Resources>
    <Style TargetType="{x:Type DataGridRow}">
      <Setter Property="Background" Value="{Binding Path=ValidationBrush}"/>
    </Style>
  </DataGrid.Resources>

更新GridDto项上的ValidationBrush会更改RowColor

修改

这有用吗:

var MyGridDtoCollection = ConvertTextDtoToGridDtos(result.Elements);
resultGrid.ItemsSource = MyGridDtoCollection;

Action a = ( ) =>
{
  foreach ( var gridDto in MyGridDtoCollection )
  {
    gridDto.ValidationBrush = Brushes.Black;
    System.Threading.Thread.Sleep( 500 );
  }
};
a.BeginInvoke( result =>
{
  a.EndInvoke( result );
} , null );