5

私はこの問題に対する非常に単純な解決策であるべきだと思っていたものを探していましたが、同様のことを尋ねているように見えるいくつかの他の質問をstackoverflowで見つけましたが、いくつかの提案された答えがありますが、私はそれらを経験しましたすべて、答えがうまくいかないか、実際には質問に答えていません。

次のように、DataGridTemplateColumns として設定したいくつかの列を持つ WPF DataGrid があります。

<DataGridTemplateColumn Header="Price 1" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Price1}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Price 2" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Price2}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

<DataGridTemplateColumn Header="Price 3" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Price3}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

「NumericCellDataTemplate」と呼ばれる再利用可能な DataTemplate を定義しました。これは、数値の書式設定、配置、値の変更時の背景の強調表示など、各列にいくつかの共通機能を提供します。これはすべて、ViewModel で定義したいくつかの特別なプロパティから派生していることに注意してください。

<DataTemplate x:Key="NumericCellDataTemplate">
    <Border Name="cellBorder" BorderThickness="0" BorderBrush="Transparent">
        <Border.Style>
            <Style TargetType="{x:Type Border}">
                <Style.Setters>
                    <Setter Property="Background" Value="Transparent" />
                </Style.Setters>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsRecentlyChanged}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource IsRecentlyChangedEnterStoryboard}" />
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource IsRecentlyChangedExitStoryboard}" />
                        </DataTrigger.ExitActions>
                    </DataTrigger>                                
                </Style.Triggers>
            </Style>
        </Border.Style>
        <TextBlock Text="{Binding Value, StringFormat='#,##0.00'}" HorizontalAlignment="Right" />
    </Border>
</DataTemplate>

これらの背景色のアニメーションのストーリーボードを設定し、値が変化したときにトリガーされるようにしました。viewModel はこれを追跡し、値ごとに IsRecentlyChanged プロパティを個別に設定/設定解除します。

<Storyboard x:Key="IsRecentlyChangedEnterStoryboard">
    <ColorAnimation Duration="0:0:0.3" To="LightSteelBlue" FillBehavior="HoldEnd" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" />
</Storyboard>
<Storyboard x:Key="IsRecentlyChangedExitStoryboard">
    <ColorAnimation Duration="0:0:0.3" To="Transparent" FillBehavior="HoldEnd" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" />
</Storyboard>

ここですべてがうまくいくようです。単純な DataGridTextColumn だけでなくカスタム DataGridTemplateColumn を使用している理由の 1 つは、バインドしているプロパティ (Price1 など) が複雑なオブジェクトであり、単純な値の型や表示される文字列だけではないことに注意してください。 . これは実際には IPropertyModel であり、ビュー レイヤーをバインドするためのいくつかの便利なプロパティを定義したインターフェイスです。

public interface IPropertyModel : INotifyPropertyChanged
{
    string Name { get; }
    bool IsRecentlyChanged { get; }
}

public interface IPropertyModel<T> : IPropertyModel
{
    T Value { get; set; }
}

したがって、私がやりたいことは、上記の DataGridTemplateColumns の定義を次のような単純な 1 行に単純化する方法を見つけることだけです。

<DataGridTemplateColumn Header="Price1" Width="60" Binding="{Binding Price1}" ContentTemplate="{StaticResource NumericCellDataTemplate}" />

もちろん、ここでの問題は、DataGridTextColumn のように DataGridTemplateColumn に Binding プロパティがないことです。DataGridCell で Style を使用して Template を新しい ControlTemplate で完全にオーバーライドし、カスタム ContentPresenter を提供するなど、多くの提案を試しました。また、使用できる Binding プロパティが既にあるという事実を利用するために、DataGridTextColumn でこれを実行しようとしましたが、Style または ContentPresenter 内からアクセスする方法がわかりません。

RelativeAncestor または TemplateBinding を使用して DataGridTemplateColumn に戻り、そこから ap:MyAttachedProperties.Binding などの添付プロパティを読み取ることについて説明している提案もありますが、一部の人が指摘しているように、DataGridCell テンプレートに入ると、私が推測するビジュアル/論理ツリーにないため、元の DataGridTemplateColumn にアクセスできなくなりましたか? そのため、多くの実験の後、それも役に立ちませんでした。

他の提案をいただければ幸いです。DataGridTextColumn、DataGridTemplateColumn、または他の誰かがより良いアイデアを持っている場合は、喜んで使用します。この例では、3 つの列のみがあり、それらすべてに対して 1 つの再利用可能な DataTemplate があります。しかし、20 以上の列があり、さまざまな種類の書式設定と表示ロジックを実行するために、いくつかの異なる再利用可能な DataTemplates の 1 つにバインドする可能性がある、より複雑なシナリオを想像してみてください。したがって、すべての列に 7 行以上の XAML コードが必要な場合、これは面倒になります。 .

ありがとう!

4

0 に答える 0