2013-08-22 2 views
0

Итак, в основном у меня есть список заданий, которые я отслеживаю в Datagrid. В этом datagrid у меня есть кнопка, я хочу быть кнопкой «Отмена», когда работа выполняется, но в остальном - кнопка «Повторить».WPF datagrid: поиск элемента управления при добавлении строки

Итак, я добавил кнопку на моей сетке:

<DataGridTemplateColumn x:Name="JobActionColumn" Header=""> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <Grid> 
       <Button Click="JobActionButton_Click" Content="Resend" Name="JobActionButton" Height="18" Width="45" Margin="0,0,0,0" /> 
      </Grid> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 

И в коде, я добавить свой объект в ObservableCollection, чтобы добавить его к сетке:

_jobs.Add(job); 
    CollectionViewSource jobViewSource = this.FindViewSource("JobViewSource"); 
    jobViewSource.View.Refresh(); // Ensure that the new job appears at the top of the grid. 
    JobDataGrid.SelectedItem = job; 

    // Note: The Controller.Completed event handler disposes the controller object. 
    Controller controller = new Controller(_historyContext); 
    _controllers.Add(controller); 
    controller.Completed += Controller_Completed; 
    controller.Process(job); 

    GetGridButton("JobActionButton", job).Content = "Cancel"; 

С GetGridButton существо:

private Button GetGridButton(string name, Job job) 
    {    
     var selectedRow = (DataGridRow)JobDataGrid.ItemContainerGenerator.ContainerFromItem(job); 

     return ExtensionMethods.FindVisualChildren<Button>(selectedRow).First(x => x.Name == name);    
    } 

Я подтвердил, что GetGridButton УНР ks с уже существующими строками. Проблема в том, что когда вы добавляете новую строку в базовый набор данных и называете это, она не может найти DataGridRow. Я предполагаю, что это происходит потому, что он еще не создан. Так, просматривая события, казалось, что событие LoadingRow будет хорошим кандидатом:

private void JobDataGrid_LoadingRow(object sender, DataGridRowEventArgs e) 
    { 
     Job job = (Job)e.Row.Item; 

     if (_controllers.FirstOrDefault(x => x.Job == job) != null) 
     { 
      var y = ExtensionMethods.FindVisualChildren<Button>(e.Row); 
      Button button = ExtensionMethods.FindVisualChildren<Button>(e.Row).First(x => x.Name == "JobActionButton"); 
      button.Content = "Cancel"; 
     } 
    } 

Итак, теперь есть DataGridRow объект перейти в FindVisualChildren, но он по-прежнему Безразлично» t найдите любые кнопки. Итак, есть ли способ получить доступ к этой кнопке в добавленной строке?

+0

MVVM - ваш друг. –

+0

Не очень полезно. – jbirzer

ответ

0

Предпочтительный способ работы с WPF называется MVVM.

Это мой взгляд на то, что вы описали:

<Window x:Class="MiscSamples.MVVMDataGrid" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MVVMDataGrid" Height="300" Width="300"> 
    <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" 
       CanUserAddRows="False"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Name}"/> 
      <DataGridTemplateColumn> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <Grid> 
          <Button Command="{Binding CancelCommand}" Content="Resend" 
            Height="20" Width="45" Margin="0,0,0,0" x:Name="btn" /> 
         </Grid> 

         <DataTemplate.Triggers> 
          <DataTrigger Binding="{Binding IsRunning}" Value="True"> 
           <Setter TargetName="btn" Property="Content" Value="Cancel"/> 
          </DataTrigger> 
         </DataTemplate.Triggers> 

        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
      </DataGridTemplateColumn> 
     </DataGrid.Columns> 
    </DataGrid> 
</Window> 

Код За:

public partial class MVVMDataGrid : Window 
{ 
    public MVVMDataGrid() 
    { 
     InitializeComponent(); 

     DataContext = Enumerable.Range(1, 5) 
           .Select(x => new Job {Name = "Job" + x}) 
           .ToList(); 
    } 
} 

Пункт данных:

public class Job: PropertyChangedBase 
{ 
    public string Name { get; set; } 

    private bool _isRunning; 
    public bool IsRunning 
    { 
     get { return _isRunning; } 
     set 
     { 
      _isRunning = value; 
      OnPropertyChanged("IsRunning"); 
     } 
    } 

    public Command CancelCommand { get; set; } 

    public Job() 
    { 
     CancelCommand = new Command(() => IsRunning = !IsRunning); 
    } 
} 

класс PropertyChangedBase (MVVM вспомогательный класс):

public class PropertyChangedBase:INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

Command класс (MVVM класс Helper):

//Dead-simple implementation of ICommand 
    //Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click) 
    public class Command : ICommand 
    { 
     public Action Action { get; set; } 

     public void Execute(object parameter) 
     { 
      if (Action != null) 
       Action(); 
     } 

     public bool CanExecute(object parameter) 
     { 
      return IsEnabled; 
     } 

     private bool _isEnabled = true; 
     public bool IsEnabled 
     { 
      get { return _isEnabled; } 
      set 
      { 
       _isEnabled = value; 
       if (CanExecuteChanged != null) 
        CanExecuteChanged(this, EventArgs.Empty); 
      } 
     } 

     public event EventHandler CanExecuteChanged; 

     public Command(Action action) 
     { 
      Action = action; 
     } 
    } 

Результат:

enter image description here

  • Обратите внимание, как я используя DataBinding для того, чтобы упростить код и снять необходимость поиска элемент в визуальном дереве и манипулирование им в процедурном коде.
  • Логика полностью отделена от представления, используя Command, который абстрагирует функциональность кнопки.
  • В коде не содержится ни одной строки кода. Только шаблон, генерирующий записи образцов.
  • Скопируйте и вставьте мой код в File -> New Project -> WPF Application и посмотрите результаты сами.
Смежные вопросы