基于行项目值的wpf datagrid单元格样式
Posted
技术标签:
【中文标题】基于行项目值的wpf datagrid单元格样式【英文标题】:wpf datagrid cell style based on row item value 【发布时间】:2017-07-22 07:23:34 【问题描述】:这应该相对容易做到,但由于某种原因,我没有让它工作。我有一个类ViewWrapper
,它有一个属性ViewGroup
和ViewGroupEditable
。我的数据网格中有一个绑定到ViewGroup
属性的列,现在如果ViewGroupEditable
属性为false,我想禁用对该单元格的编辑。所以我用简单的数据触发器创建了一个DataGridCell
样式,但它什么也没做。我错过了什么?
XAML:
<UserControl x:Class="GrimshawRibbon.Revit.Views.ViewManager.ViewManagerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:GrimshawRibbon.Revit.Views.ViewManager"
xmlns:ex="clr-namespace:GrimshawRibbon.Revit.Wpf.Extensions"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="pack://application:,,,/GrimshawRibbon;component/Revit/Wpf/Style/GrimshawTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.Resources>
<Style x:Key="dgCellStyle" TargetType="x:Type DataGridCell" BasedOn="StaticResource x:Type DataGridCell">
<Style.Triggers>
<DataTrigger Binding="Binding ViewGroupEditable" Value="True">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ex:DataGridEx x:Name="dgViews"
Style="StaticResource AzureDataGrid"
Margin="10"
AutoGenerateColumns="False"
ItemsSource="Binding Views, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
CanUserAddRows="False"
IsReadOnly="False"
SelectionMode="Extended"
SelectionUnit="FullRow"
SelectedItem="Binding SelectedRow, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
SelectedItemsList="Binding SelectedViews, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged">
<i:Interaction.Triggers>
<i:EventTrigger EventName="CellEditEnding">
<cmd:EventToCommand PassEventArgsToCommand="True" Command="Binding CellEditEndingCommand"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Width="*"/>
<DataGridTextColumn Header="ViewType" Binding="Binding ViewType" Width="100" IsReadOnly="True"/>
<DataGridTextColumn Header="ViewGroup" Binding="Binding ViewGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Width="130" CellStyle="StaticResource dgCellStyle"/>
<DataGridTextColumn Header="ViewSubGroup" Binding="Binding ViewSubGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Width="130" IsReadOnly="False"/>
<DataGridCheckBoxColumn ElementStyle="DynamicResource MetroDataGridCheckBox"
EditingElementStyle="DynamicResource MetroDataGridCheckBox"
Header="OnSheet"
Binding="Binding OnSheet, Mode=TwoWay"
IsReadOnly="True"
Width="80">
</DataGridCheckBoxColumn>
<DataGridTemplateColumn Header="ViewTemplate" Width="180">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="Binding ViewTemplate.Name" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="Binding DataContext.ViewTemplates, RelativeSource=RelativeSource AncestorType=DataGrid"
SelectedItem="Binding ViewTemplate"
DisplayMemberPath="Name">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand PassEventArgsToCommand="True"
Command="Binding DataContext.SelectChangeCommand, RelativeSource=RelativeSource AncestorType=DataGrid"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</ex:DataGridEx>
</Grid>
</UserControl>
数据网格中的每一行都绑定到一个对象,如下所示:
public class ViewWrapper : ElementWrapper
public string ViewType get; set;
public bool IsSelected get; set;
public bool OnSheet get; set;
public string ViewGroup get; set;
public string ViewSubGroup get; set;
public ViewWrapper ViewTemplate get; set;
public bool ViewGroupEditable get; set;
public bool ViewSubGroupEditable get; set;
【问题讨论】:
【参考方案1】:DataGridTextColumn
没有IsEnabled
属性,因此无法设置。您可以尝试 IsReadOnly
代替(请注意,您将禁用整个列)。
这种方法可能会让你更幸运:
<DataGridTextColumn Width="80" Header="My column header" Binding="Binding Path=MyProperty, Mode=TwoWay">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="TextBox">
<Setter Property="IsEnabled" Value="Binding IsEditingEnabled"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
您可以为列中显示的数据定义两种样式:普通样式 (ElementStyle
) 和它在编辑模式下的显示方式 (EditingElementStyle
)。尽管您可能希望在这种情况下进行更多样式设置,以使 TextBlock
和 TextBox
的外观保持一致。
或者这种方式(未经测试):
<Style x:Key="dgCellStyle" TargetType="x:Type TextBox"">
<Style.Triggers>
<DataTrigger Binding="Binding ViewGroupEditable" Value="True">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataGridTextColumn Header="ViewGroup"
Binding="Binding ViewGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"
Width="130"
EditingElementStyle="StaticResource dgCellStyle"/>
【讨论】:
所以看起来我的数据设置器正在工作。没有表现的是我的背景颜色。选择行时,它变为深蓝色。这与您所说的有关文本框的内容有关吗? @konrad 这是默认选择颜色,这应该可以帮助您***.com/a/1227929/891715【参考方案2】:我能看到的唯一问题是ViewWrapper
没有实现INotifyPropertyChanged
。你应该为你的所有属性使用这样的东西:
public class ViewWrapper : ElementWrapper, INotifyPropertyChanged
string _viewSubGroup;
public string ViewSubGroup get return _viewSubGroup; set _viewSubGroup = value; RaisePropertyChanged("ViewSubGroup");
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string propname)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
见this post 等等。
【讨论】:
它继承的ElementWrapper
类确实实现了这一点。这是一个ObservableObject
类。
确实,我错过了。很好的建议。谢谢!以上是关于基于行项目值的wpf datagrid单元格样式的主要内容,如果未能解决你的问题,请参考以下文章
WPF的DataGrid列头和行头相交的单元格怎么修改样式和填充文字
WPF的DataGrid列头和行头相交的单元格怎么修改样式和填充文字