循环访问 WPF 数据网格行和包含控件的访问



我想更改某些单元格的颜色并访问不同单元格的按钮。

我想在调用数据网格的 Loaded 事件时执行此操作。

当前数据网格:

<DataGrid SelectionUnit="FullRow" SelectionMode="Single" AutoGenerateColumns="False" Height="468" HorizontalAlignment="Left" Margin="12,0,0,238" Name="LockDataGrid" VerticalAlignment="Bottom" Width="554" LoadingRow="LockDataGrid_LoadingRow" CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn IsReadOnly="True" Header="Name" Width="200" Binding="{Binding Name}"></DataGridTextColumn>
        <DataGridTextColumn IsReadOnly="True" Header="ModuleLock" Binding="{Binding ModuleLock}"></DataGridTextColumn>
        <DataGridTextColumn IsReadOnly="True" Header="StringLock" Binding="{Binding StringLock}"></DataGridTextColumn>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button>Lock module string</Button>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button>Lock strings</Button>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

加载方法:

    private void LockDataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        DataGrid grid = (DataGrid)sender;
    }

如何迭代行和单元格?

>我要直截了当地说,您可能不想通过可视化树来实现您的目标(特别是如果它只是用按钮/设置单元格颜色做某事)......

当用户滚动数据网格时,行上的控件将进出,这意味着您需要不断监视和更新它(对于少量行,这可能不会发生,但它应该表明这不是处理事情的好方法,但是如果您真的需要走这条路,LPL 已经链接到相关的答案)。

为了在单击按钮时执行某些操作,您可能希望在这些按钮上设置命令并将它们绑定到数据模型中;此页是一个教程应用程序,描述并演示如何绑定命令 MSDN:具有模型-视图-视图模型设计模式的 WPF 应用

然后,可以使用带有绑定或数据触发器的样式来更改单元格的背景颜色(以及许多其他内容)。我已经拼凑了一个快速示例来展示这一点(尽管我没有对这个小示例使用命令绑定,但我强烈建议这样做)。

首先,您将 xaml 修改为具有背景颜色绑定,并在单击模块锁的按钮时触发一个功能。

    <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 属性设置为 Red。如上所述,可以为按钮设置一个命令,该命令可以配置为更相关(例如,命令参数可以设置为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会认出它;)之所以存在,是因为鼠标存在奇怪的聚焦行为;不幸的是,对于使用选项卡聚焦的轻微奇怪行为,您会想要其他东西,可以在这里找到:

最新更新