【问题标题】:wpf datagrid cell style based on row item value基于行项目值的wpf datagrid单元格样式
【发布时间】: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; }
    }

【问题讨论】:

    标签: c# wpf xaml datagrid


    【解决方案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 这是默认选择颜色,这应该可以帮助您stackoverflow.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 类。
    • 确实,我错过了。很好的建议。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 2011-05-12
    相关资源
    最近更新 更多