我要直截了当地说,您可能不想走视觉树来实现您的目标(特别是如果它只对按钮/设置单元格颜色做某事)......
当用户滚动数据网格时,行上的控件将进出存在,这意味着您需要不断监视和更新它(对于少量行,这可能不会发生,但它应该表明这是'这不是处理事情的好方法,但如果你真的需要走那条路,LPL 已经链接到了一个相关的答案)。
为了在单击按钮时执行某些操作,您需要在这些按钮上设置命令并将它们绑定到您的数据模型中;此页面是一个教程应用程序,它描述并展示了如何绑定命令MSDN: WPF Apps With The Model-View-ViewModel Design Pattern
然后,您可以使用具有绑定或数据触发器的样式来更改单元格的背景颜色(以及许多其他内容)。我拼凑了一个快速示例来展示这一点(虽然我没有在这个小示例中使用命令绑定,但我强烈建议这样做)。
首先,您将 xaml 修改为具有背景颜色绑定,并在 ModuleLock 的按钮单击时触发功能。
<DataGrid SelectionUnit="FullRow" SelectionMode="Single" AutoGenerateColumns="False" Name="LockDataGrid" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Header="Name" Width="200" Binding="{Binding Name}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding CellColor}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn IsReadOnly="True" Header="ModuleLock" Binding="{Binding ModuleLock}"></DataGridTextColumn>
<DataGridTextColumn IsReadOnly="True" Header="StringLock" Binding="{Binding StringLock}"></DataGridTextColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Click="Button_Click">Lock module string</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button>Lock strings</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
接下来是后面代码中的按钮单击处理程序,在此示例中,我只是将行数据的 CellColor 属性设置为红色。如上所述,可以为按钮设置一个命令,该命令可以配置为更加相关(例如,命令参数可以设置为 DataContext,默认情况下将是该行的数据)。
private void Button_Click(object sender, RoutedEventArgs e)
{
var lockModuleButton = sender as Button;
if (lockModuleButton == null)
{
return;
}
var theRowData = lockModuleButton.DataContext as Class1;
if (theRowData == null)
{
return;
}
theRowData.CellColor = "Red";
}
最后一个重要部分 - 数据类(我在其中创建了 CellColor 属性)将需要通知属性更改,以便绑定更新INotifyPropertyChanged(另请注意,我只是费心设置 CellColor 以在绑定更改时更新绑定):
using System.ComponentModel;
namespace WpfApplication7
{
class Class1 : INotifyPropertyChanged
{
private string cellColor;
public string CellColor
{
get
{
return cellColor;
}
set
{
cellColor = value;
OnPropertyChanged("CellColor");
}
}
public bool ModuleLock { get; set; }
public bool StringLock { get; set; }
public string Name { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
}
}
这是窗口打开事件中的快速代码,用于虚拟化一些数据并设置 DataGrid 的数据上下文:
public MainWindow()
{
InitializeComponent();
List<Class1> MyList = new List<Class1>();
MyList.Add(new Class1());
MyList.Add(new Class1());
MyList.Add(new Class1());
MyList.Add(new Class1());
MyList.Add(new Class1());
MyList.Add(new Class1());
LockDataGrid.ItemsSource = MyList;
}
编辑:在构建它时,我发现您要解决的实际问题是在按下按钮时锁定对这些字符串字段的访问(如果是这种情况,可能值得更新您的问题以反映这一点,如果因此,如果它满足您的需求或沿着正确的轨道,我会细化这个答案)。
不幸的是,DataGrid 似乎不是为此而设计的(无论如何我都可以看到) - 但是可以通过使用 DataGridTemplateColumn 来完成,该列具有以下内容:
<DataGridTemplateColumn Header="ModuleLock">
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="IsEditing" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Background="{Binding CellColor}" Text="{Binding ModuleLock}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Background="{Binding CellColor}" BorderThickness="0" IsReadOnly="{Binding ModuleLockFlag}" Text="{Binding ModuleLock}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
样式(LPL 会识别它;)之所以存在,是因为鼠标有奇怪的聚焦行为;不幸的是,你会想要一些其他的东西来使用标签聚焦,可以在这里找到一些奇怪的行为: