wpf 设置 DataGrid 列的样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23998136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:49:23  来源:igfitidea点击:

Setting styles for DataGrid Columns

c#wpfdatagrid

提问by Frank E

I have a DataGrid where I'm trying to set the background of each element depending on what text is being displayed in that grid cell. The grid cells are defined as follows and accessing them works correctly:

我有一个 DataGrid,我试图根据该网格单元格中显示的文本设置每个元素的背景。网格单元定义如下,访问它们可以正常工作:

<Window.Resources>
    <Style TargetType="{x:Type DataGridCell}">
        <EventSetter Event="MouseDown" Handler="Clicked" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Foreground" Value="Black"/>
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="BorderThickness" Value="1"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

The part that doesn't work is that I can't set the a style for the DataGridTextColumn, none of my setters below are doing anything. The DataGrid itself is being displayed corrrectly.

不起作用的部分是我无法为 DataGridTextColumn 设置样式,下面的任何设置器都没有做任何事情。DataGrid 本身显示正确。

        <DataGrid Name="dataGrid1" AutoGenerateColumns="False" IsReadOnly="true">
            <DataGridTextColumn>
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="{x:Type TextBlock}">
                        <Setter Property="HorizontalAlignment" Value="Center" />
                        <Setter Property="Background" Value="Black"/>
                        <Style.Triggers>
                            <Trigger Property="Text" Value="None">
                                <Setter Property="Background" Value="Aquamarine"/>
                            </Trigger>
                            <Trigger Property="Text" Value="First">
                                    <Setter Property="Background" Value="Blue"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
        </DataGrid>

Thanks in advance for any help.

在此先感谢您的帮助。

EDIT 1Updated with Answers to NETscape's questions. 1) My DataGrid is showing correctly, I'm even clicking on items in the grid and modifying the data behind it. However, I don't have a DataSource set in my XAML, just a simple DataContext in my view that points to the DataGrid.

编辑 1更新了 NETscape 问题的答案。1) 我的 DataGrid 显示正确,我什至单击了网格中的项目并修改了它后面的数据。但是,我的 XAML 中没有设置 DataSource,在我的视图中只有一个指向 DataGrid 的简单 DataContext。

2) I don't think that the problem is with my variable names since the setter property below that doesn't have a trigger also isn't showing:

2)我不认为问题出在我的变量名上,因为下面没有触发器的 setter 属性也没有显示:

 <Setter Property="HorizontalAlignment" Value="Center" />

EDIT 2Again in response to NETscape's questions/comments. I didn't post my code-behind originally because, since all my objects were displaying correctly, I wasn't looking for the problem there. But I think I was mistaken. The data binding for my grid and for the columns in the grid are different. The DataContext for my grid is an array of RowObjects. The datacontext for each DataGridTextColumn is one entry in my RowObject tied to a particular day of the week.

编辑 2再次响应 NETscape 的问题/评论。我最初没有发布我的代码隐藏,因为我所有的对象都显示正确,我没有在那里寻找问题。但我想我错了。我的网格和网格中的列的数据绑定是不同的。我的网格的 DataContext 是一个 RowObjects 数组。每个 DataGridTextColumn 的数据上下文是我的 RowObject 中的一个条目,与一周中的某一天相关联。

    DataGridTextColumn cSunday = new DataGridTextColumn();
    DataGridTextColumn cMonday = new DataGridTextColumn();
    public TimeSlice[] TimeArray = new TimeSlice[48];

        MyWnd.dataGrid1.DataContext = TimeArray; //sets DataContext for the DataGrid
        CultureInfo cu = new CultureInfo(App.CultureID);


        //creates one column
        cSunday.Header = cu.DateTimeFormat.GetDayName(DayOfWeek.Sunday);
        cSunday.Binding = new Binding("StatusSunday");
        Wnd.dataGrid1.Columns.Add(cSunday);

        cMonday.Header = cu.DateTimeFormat.GetDayName(DayOfWeek.Monday);
        cMonday.Binding = new Binding("StatusMonday");
        Wnd.dataGrid1.Columns.Add(cMonday);

EDIT 3For completeness sake, adding the working solution derived fron NETscape's answer. XAML:

编辑 3为完整起见,添加从 NETscape 的答案派生的工作解决方案。XAML:

<Window
<Window.Resources>
    <Style TargetType="{x:Type DataGridCell}">
        <EventSetter Event="MouseDown" Handler="Clicked" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Foreground" Value="Black"/>
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="BorderThickness" Value="1"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="MyDataGridTextColumnElementStyle" 
       TargetType="{x:Type TextBlock}">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="Background" Value="Black"/>
        <Style.Triggers>
            <Trigger Property="Text" Value="None">
                <Setter Property="Background" Value="Aquamarine"/>
            </Trigger>
            <Trigger Property="Text" Value="First">
                <Setter Property="Background" Value="Blue"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid Name="MainView"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Border Grid.Row ="0">
    </Border>
    <Border Grid.Row="1">
        <DataGrid Name="dataGrid1" AutoGenerateColumns="False" IsReadOnly="true"/>
    </Border>
</Grid>
</Window>

And the code in my view model for setting up the first 2 days/columns:

以及我的视图模型中用于设置前 2 天/列的代码:

public TimeSlice[] TimeArray = new TimeSlice[48];
public ViewModelr(WndCalendar Wnd)
    {


        MyWnd = Wnd;
        MyWnd.DataContext = this;
        MyWnd.dataGrid1.DataContext = TimeArray;

        cTime.Header = "";
        cTime.Binding = new Binding("TimeofDay");
        Wnd.dataGrid1.Columns.Add(cTime);

        CultureInfo cu = new CultureInfo(App.CultureID);

        cSunday.Header = cu.DateTimeFormat.GetDayName(DayOfWeek.Sunday);
        cSunday.Binding = new Binding("StatusSunday");
        Wnd.dataGrid1.Columns.Add(cSunday);
        cSunday.ElementStyle = MyWnd.FindResource("MyDataGridTextColumnElementStyle") as Style;

        cMonday.Header = cu.DateTimeFormat.GetDayName(DayOfWeek.Monday);
        cMonday.Binding = new Binding("StatusMonday");
        Wnd.dataGrid1.Columns.Add(cMonday);
        cMonday.ElementStyle = MyWnd.FindResource("MyDataGridTextColumnElementStyle") as Style;

采纳答案by Kcvin

Frank E, your Edit 2 might have given away your issue; it's always helpful to know when you're doing things programmatically!

Frank E,你的 Edit 2 可能泄露了你的问题;知道何时以编程方式做事总是很有帮助的!

Setting the Styleinside of Windows.Resourcesis saying, "hey, for any DataGridCellin this control, apply this style to it." That is why it's working properly, because after all the information is added, the styles still get applied; which is why it seems to be working.

设置Style里面Windows.Resources是说,“嘿,对于DataGridCell这个控件中的任何一个,应用这个样式。” 这就是它正常工作的原因,因为在添加了所有信息之后,样式仍然会被应用;这就是为什么它似乎有效。

Now notice you are defining a DataGridTextColumnand it's ElementStyle. That isn't being applied to all the DataGridTextColumn's which may be what you were thinking. Instead, that is being applied to that single DataGridTextColumn! Because you're not defining anything for that DataGridTextColumnit's actually being drawn in the DataGrid, but since there is no content for that column, it's Width = 0.

现在请注意,您正在定义 aDataGridTextColumn并且它是ElementStyle。这并不适用于所有DataGridTextColumn可能是您所想的。取而代之的是,这适用于那个单曲DataGridTextColumn!因为您没有定义任何内容,因为DataGridTextColumn它实际上是在 中绘制的DataGrid,但是由于该列没有内容,所以它是Width = 0.

Since you're creating the other columns programmatically, you need to apply the Style programmatically. So you should have something like this:

由于您正在以编程方式创建其他列,因此您需要以编程方式应用样式。所以你应该有这样的东西:

<Window.Resources>
    <Style TargetType="{x:Type DataGridCell}">
        <EventSetter Event="MouseDown" Handler="Clicked" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Foreground" Value="Black"/>
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="BorderThickness" Value="1"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="MyDataGridTextColumnElementStyle" 
           TargetType="{x:Type TextBlock}">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="Background" Value="Black"/>
        <Style.Triggers>
            <Trigger Property="Text" Value="None">
                <Setter Property="Background" Value="Aquamarine"/>
            </Trigger>
            <Trigger Property="Text" Value="First">
                    <Setter Property="Background" Value="Blue"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Then when you're creating your columns in code behind, do something like this:

然后,当您在后面的代码中创建列时,请执行以下操作:

cSunday.ElementStyle = MyWnd.FindResource("MyDataGridTextColumnElementStyle") as Style;

for each column that you are creating.

对于您正在创建的每一列。

From what I understand, not assigning a x:Keywill apply the style to all elements that are of type TargetType, so since we assign a x:Keyto the 2nd style, not all TextBlockwill be assigned that style, only the ones we specify.

据我了解,不分配 ax:Key会将样式应用于所有类型为 的元素TargetType,因此由于我们将 a 分配x:Key给第二个样式,并非所有元素TextBlock都会分配该样式,只有我们指定的样式。

Let me know if this helps.

如果这有帮助,请告诉我。