所以,基本上我有一个我在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 适用于已存在的行。问题是,当您向基础数据集添加新行并调用它时,它无法找到 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 ,但它仍然找不到任何按钮。那么,有没有办法让我在添加的行上访问此按钮?
答案 0 :(得分: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));
}
}
命令类(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;
}
}
结果:
File -> New Project -> WPF Application
中,然后自行查看结果。