簡體   English   中英

如何在AutoGeneratingColumn事件期間根據其值設置數據網格單元格的背景?

[英]How to set background of a datagrid cell during AutoGeneratingColumn event depending on its value?

我仍然在操縱細胞背景,所以我問了一個新問題。

用戶“HB”寫道我可以在AutoGeneratingColumn事件期間實際設置單元格樣式 - 根據值更改DataGrid單元格顏色 問題是我不知道該怎么做。

我想要的:根據每個單元格的值設置不同的背景顏色 如果值為null我也希望它不可 點擊 (我猜可以集中精力)。

我有/我想做什么:

private void mydatagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    foreach (Cell cell in e.Column)
    {
        if (cell.Value < 1)
        { 
            cell.Background = Color.Black; 
            cell.isFocusable = false; 
        } 
        else
        {
            cell.Background = Color.Pink;
        }
    }
}

這只是偽代碼。 在列自動生成期間是否可以這樣做,如果是這樣,我如何編輯我的代碼以使其有效?

我讀到了有關值轉換器的內容,但我想知道它是否可以通過編程方式進行,而無需編寫XAML。

請理解我還是C#/ WPF / DataGrid的初學者。

解決方案part1:

我用了我接受的答案。 把它放入

<Window.Resources> 
<local:ValueColorConverter x:Key="colorConverter"/>
        <Style x:Key="DataGridCellStyle1" TargetType="{x:Type DataGridCell}"> 
            <Setter Property="Padding" Value="5"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
                            <Border.Background>
                                <MultiBinding Converter="{StaticResource colorConverter}">
                                    <Binding RelativeSource="{RelativeSource AncestorType=DataGridCell}" Path="Content.Text"/>
                                    <Binding RelativeSource="{RelativeSource AncestorType=DataGridCell}" Path="IsSelected"/>
                                </MultiBinding>
                            </Border.Background>
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
</Window.Resources>

並為它制作了一個MultiBinding轉換器,所以我也可以設置所選單元格的背景顏色。

問題:

現在我只需要解決設置空單元格焦點的問題。 任何提示?

  <Style.Triggers>
        <Trigger Property="HasContent" Value="False">
            <Setter Property="Focusable" Value="False"/>
        </Trigger>
    </Style.Triggers>

這不起作用。 我在空單元格中有空字符串,但它們充滿了“空”,所以它應該可以工作,對嗎? 或者我做錯了什么:|

解決方案第2部分

因此,只要單元格值是'TextBox',上面的代碼就無法工作,所以我決定找到另一種處理它的方法,可以在我的答案中找到: https//stackoverflow.com/a/16673602 / 2296407

謝謝你試着幫我:)

我可以為你的問題提出兩種不同的解決方案:第一種是“代碼隱藏風格”(你要求但我個人認為這不是WPF中的正確方法)和更多WPF風格(更難以保存代碼) - 清潔並利用風格,觸發器和轉換器)

解決方案1.用於着色的事件處理和代碼隱藏邏輯

首先,您選擇的方法無法直接使用 - AutoGeneratingColumn事件旨在用於更改整個列的外觀,而不是逐個單元格。 因此,它可以用於,例如,根據它的顯示索引或綁定屬性將正確的樣式附加到整個列。

一般來說,第一次引發事件時,datagrid根本就沒有任何行(因此也就是單元格)。 如果您確實需要捕獲事件 - 請考慮使用DataGrid.LoadingRow事件。 你將無法讓細胞變得容易:)

那么,你做了什么:處理LoadingRow事件,獲取行(它具有Item屬性(令人驚訝:)保存你的綁定項),獲取綁定項,進行所有需要的計算,得到你需要改變的單元格和最后改變了目標細胞的風格。

這是代碼(作為項目,我使用帶有int“Value”屬性的示例對象,我用它來着色)。

XAML

   <DataGrid Name="mygrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True" LoadingRow="DataGrid_OnLoadingRow"/>

.CS

    private void DataGrid_OnLoadingRow(object sender, DataGridRowEventArgs e)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => AlterRow(e)));
    }

    private void AlterRow(DataGridRowEventArgs e)
    {
        var cell = GetCell(mygrid, e.Row, 1);
        if (cell == null) return;

        var item = e.Row.Item as SampleObject;
        if (item == null) return;

        var value = item.Value;

        if (value <= 1) cell.Background = Brushes.Red;
        else if (value <= 2) cell.Background = Brushes.Yellow;
        else cell.Background = Brushes.Green;
    }

    public static DataGridRow GetRow(DataGrid grid, int index)
    {
        var row = grid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;

        if (row == null)
        {
            // may be virtualized, bring into view and try again
            grid.ScrollIntoView(grid.Items[index]);
            row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
        }
        return row;
    }

    public static T GetVisualChild<T>(Visual parent) where T : Visual
    {
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            var v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T ?? GetVisualChild<T>(v);
            if (child != null)
            {
                break;
            }
        }
        return child;
    }

    public static DataGridCell GetCell(DataGrid host, DataGridRow row, int columnIndex)
    {
        if (row == null) return null;

        var presenter = GetVisualChild<DataGridCellsPresenter>(row);
        if (presenter == null) return null;

        // try to get the cell but it may possibly be virtualized
        var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
        if (cell == null)
        {
            // now try to bring into view and retreive the cell
            host.ScrollIntoView(row, host.Columns[columnIndex]);
            cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
        }
        return cell;

    }

解決方案2. WPF風格

此解決方案僅使用代碼隱藏進行值到顏色的轉換(假設着色的邏輯比相等比較更復雜 - 在這種情況下,您可以使用觸發器而不會弄亂轉換器)。

你做了什么:使用包含數據觸發器的樣式設置DataGrid.CellStyle屬性,該樣式檢查單元格是否在所需的列中(基於它的DisplayIndex),如果是 - 通過轉換器應用背景。

XAML

<DataGrid Name="mygrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True">
        <DataGrid.Resources>
            <local:ValueColorConverter x:Key="colorconverter"/>
        </DataGrid.Resources>
        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.DisplayIndex}" Value="1">
                        <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource colorconverter}}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>

.CS

public class ValueColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var str = value as string;
        if (str == null) return null;

        int intValue;
        if (!int.TryParse(str, out intValue)) return null;

        if (intValue <= 1) return Brushes.Red;
        else if (intValue <= 2) return Brushes.Yellow;
        else return Brushes.Green;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

UPD:如果需要為整個數據網格着色,XAML要容易得多(不需要使用觸發器)。 使用以下CellStyle:

    <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                 <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource colorconverter}}"/>
            </Style>
    </DataGrid.CellStyle>

我的意思是你可以設置列的CellStyle屬性,你不能直接操作單元格,因為它們在這個事件中不可用。 樣式可以包含DataTriggers形式的條件邏輯(需要轉換器,因為你有“小於”而不是等於)和Setters

此外,如果邏輯不是特定於列,則可以在網格本身上全局設置樣式 使用該事件的目的是操縱您無法訪問的列屬性。

我不確定你的WPF Datagrid中是否有這個屬性(Cell.Style)。 在您的情況下可能存在一些替代方案。 它適用於WinForms datagrid。

 cell.Style.BackColor = System.Drawing.Color.Black;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM