如何创建和使用自定义DataGridRow触发器

时间:2017-07-28 22:52:48

标签: wpf xaml datagrid blend prism-6

我使用Prism 6来创建我的应用程序,我需要根据日期为DataGridRows的背景着色。我开始创建一个Blend SDK Trigger来接受两个参数:MinDate和MaxDate。然后该动作将设置背景颜色。但是,在使用触发器时,我遇到了障碍。它在集合中不被接受,我似乎无法在使用DataTemplate时执行触发器。

这是触发器的代码。除了调用动作之外,它实际上并没有做任何事情,因为我想在编码逻辑以检查日期之前确保它正在执行。

public class AnniversaryTrigger: TriggerBase<DataGridRow>
{
    public DateTime MaxDate
    {
        get { return (DateTime)GetValue(MaxDateProperty); }
        set { SetValue(MaxDateProperty, value); }
    }

    public DateTime MinDate
    {
        get { return (DateTime)GetValue(MinDateProperty); }
        set { SetValue(MinDateProperty, value); }
    }

    protected override void OnAttached()
    {
        AssociatedObject.Loaded += OnLoaded;
        AssociatedObject.Unloaded += OnUnloaded;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Loaded -= OnLoaded;
        AssociatedObject.Unloaded -= OnUnloaded;
    }

    private void OnLoaded(object sender, System.Windows.RoutedEventArgs e)
    {
        AssociatedObject.DataContextChanged += OnDataContextChanged;
        Refresh();
    }

    private void OnUnloaded(object sender, System.Windows.RoutedEventArgs e)
    {
        AssociatedObject.DataContextChanged -= OnDataContextChanged;
    }

    private void Refresh()
    {
        base.InvokeActions(null);
    }

    private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        Refresh();
    }

    #region Dependency Properties
    public static readonly DependencyProperty MaxDateProperty =
        DependencyProperty.Register("MaxDate", typeof(DateTime), typeof(AnniversaryTrigger), new PropertyMetadata(null));

    public static readonly DependencyProperty MinDateProperty =
        DependencyProperty.Register("MinDate", typeof(DateTime), typeof(AnniversaryTrigger), new PropertyMetadata(null));
    #endregion
}

DataTemplate如下所示,并附加到DataGrid ItemTemplate。

<UserControl.Resources>
    <DataTemplate x:Key="AnniversaryTemplate">
        <DataGridRow>
            <i:Interaction.Triggers>
                <b:AnniversaryTrigger MinDate="{Binding MinDate}" 
                                      MaxDate="{Binding MaxDate}" >
                    <ei:ChangePropertyAction PropertyName="Background">
                        <ei:ChangePropertyAction.Value>
                            <SolidColorBrush Color="Yellow"/>
                        </ei:ChangePropertyAction.Value>
                    </ei:ChangePropertyAction>
                </b:AnniversaryTrigger>
            </i:Interaction.Triggers>
        </DataGridRow>
    </DataTemplate>
</UserControl.Resources>

这是DataGrid:

<DataGrid ItemsSource="{Binding FalseAlarmHistory}" AutoGenerateColumns="False" IsReadOnly="True" ItemTemplate="{DynamicResource AnniversaryTemplate}" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Incident ID" 
                                Binding="{Binding IncidentID}" />
            <DataGridTextColumn Header="Incident Date" 
                                Binding="{Binding IncidentDate, StringFormat=d}" />
            <DataGridTextColumn Header="Incident Time" 
                                Binding="{Binding IncidentTime}" />
            <DataGridTextColumn Header="Notes" 
                                Binding="{Binding Notes}" />
        </DataGrid.Columns>
    </DataGrid>

感谢任何指导。

事件历史记录视图模型:

public class FalseAlarmHistoryViewModel : ValidatingBindableBase, IConfirmNavigationRequest
{
    private IFalseAlarmService _service;
    private ICustomerService _custsvc;

    private string _title;
    private IEventAggregator _eventAggregator;

    public string Title { get => _title; set => SetProperty(ref _title, value); }

    public FalseAlarmHistoryViewModel(IFalseAlarmService service, ICustomerService custsvc, IEventAggregator eventAggregator)
    {
        _service = service;
        _custsvc = custsvc;
        _eventAggregator = eventAggregator;
        Title = "False Alarms History";

        _eventAggregator.GetEvent<PermitSelectedChangedEvent>().Subscribe(PermitIdChanged);
    }

    //todo Color DataGrid Rows based on the anniversary year the false alarm occurred.  
    // See https://stackoverflow.com/questions/14997250/datagrid-row-background-color-mvvm
    // Add unmapped item to the FalseAlarmHistory entity that returns the year based on the anniversary year. 0 = current year, 1 = 1 year ago, etc.
    // Translate the year number into a color that will be used on the DataGrid row.  Make the color configurable (in app.config at least).

    //todo Initial sort should be most recent first.
    private void PermitIdChanged(int obj)
    {
        FalseAlarmHistory = new ListCollectionView(_service.GetFalseAlarmHistoryByPermitId(_custsvc.CurrentPermitId).ToList());
        RaisePropertyChanged(nameof(FalseAlarmHistory));
    }

    public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
    {
        continuationCallback(true);
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        FalseAlarmHistory = new ListCollectionView(_service.GetFalseAlarmHistoryByPermitId(_custsvc.CurrentPermitId).ToList());
        RaisePropertyChanged(nameof(FalseAlarmHistory));
    }

    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
        return true;
    }

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {
    }

    #region Commands
    #endregion
    #region Event Handlers
    #endregion
    #region Bound Controls
    public ICollectionView FalseAlarmHistory { get; private set; }


    #endregion
    #region Bound Commands
    #endregion
}

1 个答案:

答案 0 :(得分:0)

所以,我想的是你在事件模型中添加一个属性,该属性将根据事件和周年日期计算。通过它的声音,你必须以某种方式将周年日期纳入事件模型。您可以从数据中执行此操作,或通过属性,构造函数,函数等将其传递给事件模型。

假设您调用属性IncidentAgeBucket并创建类型AgeBucket

// Inside Incident Model
public AgeBucket IncidentAgeBucket { get {
    // AgeBucket calculation logic goes here
    // Check to make sure you have an anniversary date first...
    // There are a few ways to approach setting this value, use one that you are comfortable with 
    }
}

// New enumeration to use (name these something more to your liking)
public enum AgeBucket{
    OneYear,
    TwoYear,
    ThreeYear
}

因此,如果日期在周年纪念日的年份之内,则将IncidentAgeBucket的值返回AgeBucket.OneYear,然后两年后返回AgeBucket.TwoYear等等。

在XAML中,根据属性中的值添加RowStyle

<DataGrid x:Name="IncidentList" ItemsSource="{Binding Incidents}" ...>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Incident Number" Binding="{Binding IncidentNumber}"/>
        ...
    </DataGrid.Columns>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IncidentAgeBucket}" Value="{x:Static local:AgeBucket.OneYear}">
                    <Setter Property="Background" Value="LightGreen"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding IncidentAgeBucket}" Value="{x:Static local:AgeBucket.TwoYear}">
                    <Setter Property="Background" Value="LightBlue"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding IncidentAgeBucket}" Value="{x:Static local:AgeBucket.ThreeYear}">
                    <Setter Property="Background" Value="LightPink"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowStyle>
</DataGrid>

您可能需要稍微使用{x:Static local:AgeBucket.OneYear}语法。本地命名空间可能不是您使用的。如果您最终嵌套枚举,那么还需要做其他事情才能使其工作。 A seemingly good reference为此。

我希望这会让你知道除触发路线以外的其他方向。这对我来说似乎更直接。

如果这是偏离基础,请告诉我,我将废弃这个答案。评论太多了!希望这会有所帮助。