【问题标题】:Make first row of DataGrid ReadOnly使 DataGrid 的第一行只读
【发布时间】:2012-02-08 14:58:41
【问题描述】:

我正在使用 DataGrid 在我的 WPF 应用程序中显示用户权限。

DataGrid 的第一行将始终包含为其显示权限的项目的所有者。

此所有者在创建项目时设置,不能直接从 DataGrid 更改。

那么我的问题是。

我怎样才能使第一行只读,也许给它一个特定的样式,以便背景可以改变?

【问题讨论】:

  • 显然,您的所有者首先出现在网格中只是巧合,行“可编辑性”的真正驱动因素应该是人的角色。

标签: wpf datagrid


【解决方案1】:

你需要一个触发器,唯一的问题是在 wpf 数据网格上获取行索引非常糟糕,所以我倾向于做这样的事情:

    <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsOwner}" Value="true">
                        <Setter Property="IsEnabled" Value="False"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>

我知道对象上的属性值对于该特定行是唯一的。因此,如果存在唯一 ID 或所有者始终拥有的东西,您可以绑定到该 ID。

setter 属性为“IsEnabled”,因为 datagridrow 不包含只读属性,但这将阻止用户修改行。

【讨论】:

  • 谢谢。那效果很好。你说的对。获取索引非常困难。
  • 我很高兴这对 OP 有效,但请注意 IsEnabled 不仅仅意味着“只读”。这也意味着无法选择该行,并禁用点击事件处理。
【解决方案2】:

这是我的看法。前面的示例会很好,我的示例用于演示获取对细胞外观的低级别控制的方法。在 WPF 中,DataGridRow 只是一个逻辑容器,您只能对其使用“附加”属性,例如EnabledFontSizeFontWeight 等,因为它们会向下传播到单元级别) ,但实际控件的外观是在单元格级别定义的。

用于只读内容的 TextBlock 通常看起来比禁用的 texbox 更干净,而且您可能希望为单元格的只读和可编辑模式应用完全不同的样式,为此您必须执行类似于下面代码的操作。

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ReadOnlyRows
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += (o, e) =>
            {
                this.g.ItemsSource = new List<Person>(2)
                {
                    new Person(){ Name="Dmitry", Role="Owner" },
                    new Person(){ Name="Jody", Role="BA" }
                };
            };
        }
    }

    public class Person
    {
        public string Role
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }
    }

    public class PersonServices
    {
        // that shouldn't be in template selector, whould it?
        public static bool CanEdit(Person person)
        {
            return person.Role != "Owner";
        }
    }

    public class TemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            Person person = item as Person;

            if (person == null) return null;

            string templateName = PersonServices.CanEdit(person) ? "EditableDataTemplate" : "ReadOnlyDataTemplate";

            return (DataTemplate)((FrameworkElement)container).FindResource(templateName);
        }
    }

    public class EditingTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            Person person = item as Person;

            if (person == null) return null;

            string templateName = PersonServices.CanEdit(person) ? "EditableEditingDataTemplate" : "ReadOnlyEditingDataTemplate";

            return (DataTemplate)((FrameworkElement)container).FindResource(templateName);
        }
    }
}

XAML:

<Window x:Class="ReadOnlyRows.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ReadOnlyRows"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="g" AutoGenerateColumns="False"
                  CanUserAddRows="False">
            <DataGrid.Resources>
                <DataTemplate x:Key="EditableEditingDataTemplate">
                    <TextBox Text="{Binding Name}" />
                </DataTemplate>

                <DataTemplate x:Key="ReadOnlyEditingDataTemplate">
                    <TextBlock Text="{Binding Name}" FontWeight="Bold" />
                </DataTemplate>

                <DataTemplate x:Key="EditableDataTemplate">
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>

                <DataTemplate x:Key="ReadOnlyDataTemplate">
                    <TextBlock Text="{Binding Name}" FontWeight="Bold" />
                </DataTemplate>

                <local:TemplateSelector x:Key="TemplateSelector" />
                <local:EditingTemplateSelector x:Key="EditingTemplateSelector" />
            </DataGrid.Resources>

            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Name"
                    CellTemplateSelector="{StaticResource TemplateSelector}"
                    CellEditingTemplateSelector="{StaticResource EditingTemplateSelector}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

【讨论】:

    猜你喜欢
    • 2011-01-03
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2010-12-26
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多