基于行项目值的wpf datagrid单元格样式

Posted

技术标签:

【中文标题】基于行项目值的wpf datagrid单元格样式【英文标题】:wpf datagrid cell style based on row item value 【发布时间】:2017-07-22 07:23:34 【问题描述】:

这应该相对容易做到,但由于某种原因,我没有让它工作。我有一个类ViewWrapper,它有一个属性ViewGroupViewGroupEditable。我的数据网格中有一个绑定到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)。尽管您可能希望在这种情况下进行更多样式设置,以使 TextBlockTextBox 的外观保持一致。

或者这种方式(未经测试):

 <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 单元格如何默认单击一次点中

WPF的DataGrid列头和行头相交的单元格怎么修改样式和填充文字

WPF的DataGrid列头和行头相交的单元格怎么修改样式和填充文字

WPF DataGrid 将单元格绑定到具有动态列的数据模型

无法编辑我的 DataGrid WPF Framework 4.5 的单元格