Как выделить строку и принудительно обновить строку / ячейку в WPF DataGrid? - PullRequest
3 голосов
/ 15 марта 2012

Это мой первый вопрос о SOF, поэтому, пожалуйста, будьте осторожны со мной:)

У меня есть простая таблица данных WPF, определенная в XAML.Приложение загружает «пользовательские» данные (FirstName, LastName) в сетку из текстового файла, и после загрузки записей из текстового файла пользователь нажимает кнопку отправки, я хочу перебирать элементы в списке и отправлять каждыйстрока в веб-сервисе, который создает пользователей и затем отображает ответ от веб-сервиса в сетке.

Чтобы информировать пользователя, я хочу как-то выделить текущую отправляемую строку, и я хочу, чтобы сообщениепоявляются сразу после получения ответа.Если сообщение является ошибкой, выделите строку красным, в случае успеха выделите ее зеленым цветом.

Кажется достаточно простым ...

У меня есть простой класс 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);

Пока все хорошо.Теперь я хочу отправить каждую из строк моей сетки в веб-сервис, который создает пользователей.Единственные параметры, которые требует 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 ]

2 голосов
/ 16 марта 2012

Прежде всего вы можете привязать bacgroundcolor к свойству в стиле, поместив этот код в свой XAML в DataGrid блок

        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Setter Property="Background" Value="{Binding Path=Color}"/>
            </Style>
        </DataGrid.RowStyle>

, если вы хотите обновить пользовательский интерфейс в реальном времени, вы должны использовать рабочий фонотправляющих пользователей

            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();
0 голосов
/ 16 марта 2012

Это может быть вариант:

Добавьте следующее к GridDto

private Brush validationBrush = Brushes.White;

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

И это внутри тега DataGrid в Xaml

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

ОбновлениеValidationBrush на элементе GridDto изменит 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 );
...