【问题标题】:WPF Style issue in WPF DatagridWPF Datagrid 中的 WPF 样式问题
【发布时间】:2012-11-06 12:09:47
【问题描述】:

我有一个 WPF 数据网格,并且我已将它与 observablecollection 绑定。它工作正常,但问题是我在运行时在单元格级别应用了样式。下面提到了一个示例方法 ApplyStyleAtCellLevelInDataGrid()。我必须调用此方法两次才能显示 WPF DataGrid 中样式的效果。为什么会这样……

这里是 XAML

 <Style x:Key="BaseStyle"  TargetType="{x:Type TextBlock}">
     <Setter Property="Background" Value="Transparent"/>
     <Setter Property="Foreground" Value="Black"/>        
     <Setter Property="FontSize" Value="10"/>
     <Setter Property="TextAlignment" Value="Center"/>
 </Style>

<Style TargetType="{x:Type TextBlock}" x:Key="Col1Style" BasedOn="{StaticResource BaseStyle}">

        <Setter Property="Background">
            <Setter.Value>
                <SolidColorBrush Color="Tomato"/>
            </Setter.Value>
        </Setter>            

        <Style.Triggers>
            <EventTrigger RoutedEvent="Binding.TargetUpdated">
                <BeginStoryboard HandoffBehavior="Compose">
                    <Storyboard TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)">
                    <ColorAnimation Duration="0:0:1.5" To="DarkRed"  AutoReverse="True" RepeatBehavior="1" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>

        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="FontSize" Value="10"></Setter>
        <Setter Property="Foreground" Value="Black"></Setter>           
    </Style>

XAML 中的网格声明

<DataGrid Name="dataGrid1"  ItemsSource="{Binding Values}" CellStyle="{StaticResource DGCellStyle}" SnapsToDevicePixels="True" UseLayoutRounding="False">

  <DataGrid.Columns>
      <DataGridTextColumn  Header="Value" Binding="{Binding Value1, Mode=OneWay, NotifyOnTargetUpdated=True}" Width="0.25*"/>
      <DataGridTextColumn Header="Value 1" Binding="{Binding Value2, Mode=OneWay, NotifyOnTargetUpdated=True}" Width="0.25*"/>
      <DataGridTextColumn Header="Value 2" Binding="{Binding Value3, Mode=OneWay, NotifyOnTargetUpdated=True}" Width="0.25*"/>
      <DataGridTextColumn Header="Value 3" Binding="{Binding Value4, Mode=OneWay, NotifyOnTargetUpdated=True}" Width="0.25*"/>
   </DataGrid.Columns>           
 </DataGrid>

代码

 private void ApplyStyleAtCellLevelInDataGrid()

    {
        if (Values == null || Values.Count == 0)
        {
            Values = new ObservableCollection<MyClass>();
            Values.Add(new MyClass { Value1 = "1", Value4 = "2", Value2 = "4", Value3 = "3" });
            Values.Add(new MyClass { Value1 = "2", Value4 = "3", Value2 = "5", Value3 = "7" });
            Values.Add(new MyClass { Value1 = "3", Value4 = "4", Value2 = "7", Value3 = "2" });
            Values.Add(new MyClass { Value1 = "4", Value4 = "4", Value2 = "8", Value3 = "6" });
        }
        else
        {
            foreach (var item in Values)
            {
                MyClass c = item as MyClass;
                c.Value1 = _rand.Next(0, 100).ToString();         
                c.Value2 = _rand.Next(0, 100).ToString();
                c.Value3 = _rand.Next(0, 100).ToString();
                c.Value4 = _rand.Next(0, 100).ToString();
            }
        }

        //////////////

        DataGridCell cell = GetCell(1, 1);

        Style defaultStyle = (Style)FindResource("NewStyle");
        ((TextBlock)cell.Content).Style = defaultStyle;

        cell = GetCell(1, 2);
        defaultStyle = (Style)FindResource("NewStyleExtended");
        ((TextBlock)cell.Content).Style = defaultStyle;

        cell = GetCell(2, 2);
        defaultStyle = (Style)FindResource("NewStyle");
        ((TextBlock)cell.Content).Style = defaultStyle;

        cell = GetCell(2, 3);
        defaultStyle = (Style)FindResource("Col1Style");
        ((TextBlock)cell.Content).Style = defaultStyle;
    }


 private void Window_Loaded(object sender, RoutedEventArgs e)
    {         
// Single call of this method does not work,

I have to call two times then it shows the effect

        ApplyStyleAtCellLevelInDataGrid(); 
        ApplyStyleAtCellLevelInDataGrid();
    }

【问题讨论】:

    标签: wpf datagrid wpfdatagrid styling


    【解决方案1】:

    将样式的TargetTypeTextBlock 更改为DataGridCell,然后将样式应用为DataGrid.CellStyle。由于您已经将CellStyle 设置为DGCellStyle,因此您可能必须合并这两种样式。

    此外,您需要将基本样式中的TextAlignment 更改为HorizontalAlignment,因为TextAlignment 不是DataGridCell 的属性

    <Style x:Key="BaseStyle"  TargetType="{x:Type DataGridCell}">
         <Setter Property="Background" Value="Transparent"/>
         <Setter Property="Foreground" Value="Black"/>        
         <Setter Property="FontSize" Value="10"/>
         <Setter Property="HorizontalAlignment" Value="Center"/>
     </Style>
    
    <Style TargetType="{x:Type DataGridCell}" x:Key="Col1Style" BasedOn="{StaticResource BaseStyle}">
        <Setter Property="Background">
            <Setter.Value>
                <SolidColorBrush Color="Tomato"/>
            </Setter.Value>
        </Setter>            
    
        <Style.Triggers>
            <EventTrigger RoutedEvent="Binding.TargetUpdated">
                <BeginStoryboard HandoffBehavior="Compose">
                    <Storyboard TargetProperty="(DataGridCell.Background).(SolidColorBrush.Color)">
                    <ColorAnimation Duration="0:0:1.5" To="DarkRed"  AutoReverse="True" RepeatBehavior="1" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>
    

    <DataGrid CellStyle="{StaticResource Col1Style}" ... />
    

    【讨论】:

    • 感谢您的回答,但我的邮件问题是为什么我要调用 ApplyStyleAtCellLevelInDataGrid(); 2次在Window_Loaded事件中显示样式的效果?调用一次不会在屏幕上显示任何内容
    • @AsadNaeem 我最好的猜测是它与 WPF 的 DispatcherPriority 有关,并且第一次运行是创建 Values 集合,您的 Grid 绑定到,或者DataGrid 项目尚未完成渲染,或者在渲染过程中应用了默认样式并覆盖了您的自定义样式,因此这就是需要第二次运行的原因。不过,如果不设置测试场景,我将无法确定。
    【解决方案2】:

    您可能对实现 DataTemplateSelector 感兴趣。此对象用于提供任何数据项的显示逻辑。

    这里有一个快速教程:http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector

    【讨论】:

    • 感谢您的回答,但我的邮件问题是为什么我要调用 ApplyStyleAtCellLevelInDataGrid();在 Window_Loaded 事件中显示样式的效果?调用一次不会在屏幕上显示任何内容
    • 我不知道。但是 WPF 中有一些接口旨在根据自定义逻辑修改样式,而您没有使用它们。我的回答是:也许如果你使用手头的工具而不是绕过它,你甚至不需要你的“ApplystyleAtCellLevel”函数。
    【解决方案3】:

    在 App.xaml 中添加

    "xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit" 在应用程序标签中。

    &lt;Application.Resources&gt;标签中添加

    <Style x:Key="ColumnHeaderStyle" TargetType="{x:Type dg:DataGridColumnHeader}">
        <Setter Property="HorizontalAlignment" Value="Center" />
    </Style>
    
    <Style x:Key="CellRightAlign" TargetType="{x:Type dg:DataGridCell}">
        <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>
    

    现在在代码后面添加 AutoGeneratedColumns 事件到您的数据网格

    Style RightAlign = (Style)FindResource("CellRightAlign");
    yourGrid.Columns[0].CellStyle = RightAlign;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-03
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      • 1970-01-01
      相关资源
      最近更新 更多