7

標準 (WPF ツールキット) データ グリッドがあります。一部の列 (明示的に定義されている) は、パーセンテージとして表示する必要があります。値が 0 未満の場合、一部の列を赤で表示する必要があります (2 つの列のセットは同じではありません)。StringFormatとをそれぞれ使用して、これらの要件を実装しようとしStyleました。私のXAML:

<Window xmlns:local="clr-namespace:myNamespace"
        xmlns:tk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit">
    <Window.Resources>
        <local:ValueConverter x:Key="valueToForeground" />
        <Style TargetType="{x:Type tk:DataGridCell}">
            <Setter Property="Foreground"
                    Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource valueToForeground}}" />
        </Style>
    </Window.Resources>
    <Grid>
        <tk:DataGrid AutoGenerateColumns="False"
                     ItemsSource="{Binding Path=myClass/myProperty}">
            <tk:DataGrid.Columns>
                <tk:DataGridTextColumn Header="A"
                                       Binding="{Binding colA}" />
                <tk:DataGridTextColumn Header="B"
                                       Binding="{Binding colB, StringFormat=\{0:P\}}" />
                <tk:DataGridTextColumn Header="C"
                                       Binding="{Binding colC, StringFormat=\{0:P\}}" />
                <tk:DataGridTextColumn Header="D"
                                       Binding="{Binding colD, StringFormat=\{0:P\}}" />
            </tk:DataGrid.Columns>
        </tk:DataGrid>
    </Grid>
</Window>

そして、関連するコンバーター:

namespace myNamespace
{
    public class ValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            SolidColorBrush brush = new SolidColorBrush(Colors.Black);

            Double doubleValue = 0.0;
            if (value != null)
            {
                if (Double.TryParse(value.ToString(), out doubleValue))
                {
                    if (doubleValue < 0)
                        brush = new SolidColorBrush(Colors.Red);
                }
            }
            return brush;
        }

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

それはすべてかなり標準的だと思いますが、問題はコンバーターがTextを通過した後に値を取得するStringFormatことであり、その時点でそれを正しく解析することは困難です (実際には、すべての列が同じ形式であるとは限らないため)。を取り出すStringFormatsと、コンバーターは正常に動作し、テキストは赤で表示されます。明らかな何かが欠けていますか?これを回避する簡単な方法はありますか? 今考えられる唯一のことは、フォーマットを別のコンバーターに移動することであり、それがうまくいくとは確信していません。

4

3 に答える 3

6

Pathに異なるプロパティが必要であるBindingが、それ以外はCellStyle各に似ているという同様の状況がありましたDataGridColumn。カスタムでこれを解決しましたMarkupExtension。あなたの場合、それはこのようになります

<tk:DataGrid AutoGenerateColumns="False" 
                ItemsSource="{Binding MyItems}">
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn Header="A" 
                               Binding="{Binding colA}" />
        <tk:DataGridTextColumn Header="B" 
                               Binding="{Binding colB, StringFormat=\{0:P\}}"
                               CellStyle="{markup:ForegroundCellStyle PropertyName=colB}"/>
        <tk:DataGridTextColumn Header="C" 
                               Binding="{Binding colC, StringFormat=\{0:P\}}"
                               CellStyle="{markup:ForegroundCellStyle PropertyName=colC}"/>
        <tk:DataGridTextColumn Header="D" 
                               Binding="{Binding colD, StringFormat=\{0:P\}}"
                               CellStyle="{markup:ForegroundCellStyle PropertyName=colD}"/>
    </tk:DataGrid.Columns>
</tk:DataGrid>

次に、依存するforをForegroundCellStyleExtension作成しますStyleDataGridCellPropertyName

ForegroundCellStyleExtension

public class ForegroundCellStyleExtension : MarkupExtension
{
    public ForegroundCellStyleExtension() { }
    public ForegroundCellStyleExtension(string propertyName)
    {
        PropertyName = propertyName;
    }

    public string PropertyName
    {
        get;
        set;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        IProvideValueTarget service = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
        DependencyObject targetObject = service.TargetObject as DependencyObject;
        if (targetObject == null)
        {
            return null;
        }

        Binding foregroundBinding = new Binding
        {
            Path = new PropertyPath(PropertyName),
            Converter = new ValueConverter()
        };
        Style foregroundCellStyle = new Style(typeof(DataGridCell));
        foregroundCellStyle.Setters.Add(new Setter(DataGridCell.ForegroundProperty, foregroundBinding));

        return foregroundCellStyle;
    }
}

また、他Settersに使用したいものがある場合は、それらを別のパラメータで に含めることができますMarkupExtension

<Window.Resources>
    <Style x:Key="dataGridCellStyle" TargetType="{x:Type tk:DataGridCell}">
        <Setter Property="Background" Value="Blue"/>
    </Style>
</Window.Resources>
<!-- ... -->
<tk:DataGridTextColumn Header="B" 
                       Binding="{Binding colB, StringFormat=\{0:P\}}"
                       CellStyle="{markup:ForegroundCellStyle colB, {StaticResource dataGridCellStyle}}"/>

そしてForegroundCellStyleExtension、2番目のパラメーターを使用しBasedOnますDataGridCell Style

ForegroundCellStyleExtension withBasedOn

public class ForegroundCellStyleExtension : MarkupExtension
{
    public ForegroundCellStyleExtension() { }
    public ForegroundCellStyleExtension(string propertyName, Style basedOnCellStyle)
    {
        PropertyName = propertyName;
        BasedOnCellStyle = basedOnCellStyle;
    }

    public string PropertyName
    {
        get;
        set;
    }
    public Style BasedOnCellStyle
    {
        get;
        set;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        IProvideValueTarget service = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
        DependencyObject targetObject = service.TargetObject as DependencyObject;
        if (targetObject == null)
        {
            return null;
        }

        Binding foregroundBinding = new Binding
        {
            Path = new PropertyPath(PropertyName),
            Converter = new ValueConverter()
        };
        Style foregroundCellStyle = new Style(typeof(DataGridCell), BasedOnCellStyle);
        foregroundCellStyle.Setters.Add(new Setter(DataGridCell.ForegroundProperty, foregroundBinding));

        return foregroundCellStyle;
    }
}
于 2012-05-29T11:56:44.460 に答える
2

次のように、各列のセル スタイルを指定します。

<DataGridTextColumn Header="ColA" Binding="{Binding colA, StringFormat=\{0:P\}}">
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="Foreground" 
                    Value="{Binding colA, Converter={StaticResource valueToForeground}}" />
         </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

<DataGridTextColumn Header="ColB" Binding="{Binding colB, StringFormat=\{0:P\}}">
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="Foreground" 
                    Value="{Binding colB, Converter={StaticResource valueToForeground}}" />
         </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

... 

コンバーターを変更します

public class ValueConverter : IValueConverter
{
    public object Convert(
                object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((double) value < 0) ? Brushes.Red : Brushes.Black;
    }

    public object ConvertBack(
                object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}

ここに画像の説明を入力

于 2012-05-29T09:54:52.187 に答える
1

私が見つけた最も簡単な方法は、item/content.text の代わりに完全なアイテムをコンバーターのみにバインドすることです。次に、アイテムとパラメーターの値について心配する必要があるセルでやりたいことを行うことができます。

あなたのセルスタイルで:

 <Setter Property="Foreground"
     Value="{Binding Converter={StaticResource valueToForeground}}" />

そしてあなたのコンバーターコードで:

public object Convert(object value, Type targetType,
    object parameter, System.Globalization.CultureInfo culture)
{
    SolidColorBrush brush = new SolidColorBrush(Colors.Black);    

    Double doubleValue = 0.0;
    if (value != null)
    {
        mydatatype data = value as mydatatype;
        //your logic goes here and also can play here with your dataitem. 
        if (Double.TryParse(data.CollD.ToString(), out doubleValue))
        {
            if (doubleValue < 0)
               brush = new SolidColorBrush(Colors.Red);
        }        
    }
    return brush;
}
于 2012-05-29T13:21:09.823 に答える