C# WPF datagrid:添加行时查找控件
所以,基本上我有一个在数据网格中跟踪的作业列表。在该datagrid中,我有一个按钮,我希望在作业运行时成为“取消”按钮,但在其他情况下是“重试”按钮 因此,我已将按钮添加到我的网格中:C# WPF datagrid:添加行时查找控件,c#,wpf,datagrid,C#,Wpf,Datagrid,所以,基本上我有一个在数据网格中跟踪的作业列表。在该datagrid中,我有一个按钮,我希望在作业运行时成为“取消”按钮,但在其他情况下是“重试”按钮 因此,我已将按钮添加到我的网格中: <DataGridTemplateColumn x:Name="JobActionColumn" Header=""> <DataGridTemplateColumn.CellTemplate> <DataTemplate> &
<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>
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);
}
private按钮GetGridButton(字符串名称、作业)
{
var selectedRow=(DataGridRow)JobDataGrid.ItemContainerGenerator.ContainerFromItem(作业);
返回ExtensionMethods.FindVisualChildren(selectedRow).First(x=>x.Name==Name);
}
我已经确认GetGridButton可以处理已经存在的行。问题是,当您向基础数据集添加新行并调用它时,它找不到DataGridRow。我想这是因为它还没有被创建。因此,从事件来看,加载行事件似乎是一个很好的候选者:
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";
}
}
private void JobDataGrid\u LoadingRow(对象发送方,DataGridRowEventArgs e)
{
Job Job=(Job)e.Row.Item;
if(_controllers.FirstOrDefault(x=>x.Job==Job)!=null)
{
var y=ExtensionMethods.FindVisualChildren(e.Row);
Button Button=ExtensionMethods.FindVisualChildren(e.Row).First(x=>x.Name==“JobActionButton”);
button.Content=“取消”;
}
}
因此,现在有一个DataGridRow对象要传递到FindVisualChildren,但它仍然找不到任何按钮。那么,我有没有办法访问添加行上的此按钮?使用WPF的首选方法是调用 这是我对你所描述的内容的看法:
<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 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帮助程序类):
命令类(MVVM帮助程序类):
结果:
- 请注意,我是如何利用这一点来简化代码并消除在可视化树中查找元素以及在过程代码中对其进行操作的需要的
- 通过使用抽象按钮功能的方法,逻辑与视图完全解耦
- 代码隐藏中没有一行代码。仅生成示例条目的样板文件
- 在
文件->新项目->WPF应用程序中复制并粘贴我的代码,然后自己查看结果
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);
}
}
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));
}
}
//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;
}
}