我正在使用DataGrid在我的WPF应用程序中显示用户权限。
DataGrid的第一行将始终包含为其显示权限的项目的所有者。
在创建项目时设置此所有者,并且无法直接从DataGrid更改。
我的问题是。
如何创建第一行ReadOnly,并且可能给它一个特定的样式,以便可以更改背景?
答案 0 :(得分:5)
你需要一个触发器,唯一的问题是在wpf datagrid上获取行索引非常糟糕,所以我倾向于这样做:
<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或所有者总是拥有的东西,你可以绑定它。
setter属性为'IsEnabled',因为datagridrow不包含readonly的属性,但这将阻止用户修改该行。
答案 1 :(得分:1)
这是我的看法。上一个样本对你说得很好,我的样本用于演示获取对细胞外观的低级控制的方法。在WPF中,DataGridRow
只是一个逻辑容器,您只能使用“附加”属性,例如Enabled
,FontSize
,FontWeight
等等。传播到细胞水平),但实际控制的外观是在细胞水平上定义的。
TextBlock for readonly通常看起来比禁用的texbox更干净,你也可能想要为你的单元格的只读和可编辑模式应用完全不同的样式,为此你必须做的有点类似于下面的代码。< / p>
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);
}
}
}
<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>