下面给你详细讲解一下基于Silverlight DataGrid中无代码设置开始与结束日期DatePicker的实现方法的完整攻略。
问题概述
在Silverlight应用程序中使用DataGrid控件时,常常需要使用DatePicker控件来设置开始和结束日期筛选条件,但是如何无代码来实现这个功能呢?
解决方案
在Silverlight DataGrid控件中,如何无代码地设置开始和结束日期DatePicker控件,具体步骤如下:
步骤一
首先,在XAML中添加开始日期和结束日期的DatePicker控件:
<StackPanel Orientation="Vertical">
<DatePicker x:Name="datePickerStart" Width="120" Margin="10,5" SelectedDate="{Binding StartDate, Mode=TwoWay}" />
<DatePicker x:Name="datePickerEnd" Width="120" Margin="10,5" SelectedDate="{Binding EndDate, Mode=TwoWay}" />
</StackPanel>
步骤二
然后,在DataGrid的样式中添加样式后台代码:
<DataGrid.Resources>
<Style TargetType="sdk:DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sdk:DataGridColumnHeader">
<Grid x:Name="Root" Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter
Grid.Row="0"
Grid.Column="0"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<ComboBox
x:Name="cmbFilter"
Grid.Row="0"
Grid.Column="1"
ItemsSource="{Binding DataContext.FilterableFields, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=sdk:DataGrid}}"
SelectedItem="{Binding FilterField}"
VerticalAlignment="Center"
Width="120"/>
<StackPanel
x:Name="stackDates"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Orientation="Horizontal"
HorizontalAlignment="Center"
Visibility="{Binding FilterVisibility}">
<TextBlock
x:Name="txtFromDate"
HorizontalAlignment="Center"
Margin="3,0,3,0"
Text="FromDate"/>
<sdk:DatePicker
x:Name="datePickerStart"
SelectedDate="{Binding StartDate, Mode=TwoWay}"
Width="120"/>
<TextBlock
x:Name="txtToDate"
HorizontalAlignment="Center"
Margin="3,0,3,0"
Text="ToDate"/>
<sdk:DatePicker
x:Name="datePickerEnd"
SelectedDate="{Binding EndDate, Mode=TwoWay}"
Width="120"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
示例
下面分别给出两个示例,来说明如何在Silverlight DataGrid中无代码设置开始和结束日期DatePicker控件:
示例一:绑定列表数据
假设我们有一个列表数据,我们需要在列表的标题行中添加开始和结束日期的筛选控件。在实现这个需求时,我们需要在数据模型类中添加StartDate和EndDate属性,并继承IEditableObject接口:
public class MyDataItem : IEditableObject
{
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
// IEditableObject 接口方法实现
public void BeginEdit()
{
// 实现备份操作
}
public void CancelEdit()
{
// 实现恢复备份操作
}
public void EndEdit()
{
// 不需要实现,因为 Silverlight 的数据绑定框架会自动提交
}
}
然后,我们需要使用ObservableCollection
<sdk:DataGrid
x:Name="dataGrid"
ItemsSource="{Binding MyDataItems}"
AutoGenerateColumns="False"
IsReadOnly="True"
LoadingRow="DataGrid_LoadingRow"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
FilterableFields="{Binding FilterableFields, Mode=OneWay, NotifyOnTargetUpdated=True}"
TargetUpdated="DataGrid_TargetUpdated">
</sdk:DataGrid>
在事件处理程序中,我们需要初始化FilterableFields属性的值,并设置DataContext对象的FilterVisibility属性的值:
private void DataGrid_TargetUpdated(object sender, DataTransferEventArgs e)
{
// 初始化 FilterableFields 属性
foreach (var prop in typeof(MyDataItem).GetProperties())
{
var att = prop.GetCustomAttributes(typeof(DisplayAttribute), true).FirstOrDefault() as DisplayAttribute;
var name = att != null && !string.IsNullOrEmpty(att.Name) ? att.Name : prop.Name;
FilterableFields.Add(name);
}
// 设置 FilterVisibility 属性
if (FilterableFields.Count > 0)
{
var header = (sdk:DataGridColumnHeader)e.TargetObject;
var ctx = header.DataContext as MyDataListViewModel;
var fi = ctx.GetType().GetProperty("FilterVisibility");
if (fi != null)
{
var value = Visibility.Collapsed;
var fields = ctx.GetType().GetProperty("FilterableFields").GetValue(ctx, null) as List<string>;
if (fields != null && fields.Contains(header.Content.ToString()))
{
value = Visibility.Visible;
}
fi.SetValue(ctx, value, null);
}
}
}
此时,我们已经完成了Silverlight DataGrid中的无代码设置开始和结束日期DatePicker控件的实现。我们可以在代码中使用下面这样的方式来绑定筛选条件:
CollectionViewSource.GetDefaultView(MyDataItems).Filter = new Predicate<object>(item =>
{
var i = (MyDataItem)item;
// 开始日期筛选条件
if (StartDate.HasValue)
{
if (i.StartDate < StartDate.Value)
{
return false;
}
}
// 结束日期筛选条件
if (EndDate.HasValue)
{
if (i.EndDate > EndDate.Value)
{
return false;
}
}
// 其它筛选条件
...
return true;
});
示例二:手动添加列
如果我们手动添加列,我们需要在列头控件的Loaded事件处理程序中添加DatePicker控件:
<sdk:DataGrid x:Name="dataGrid" ItemsSource="{Binding MyDataItems}" AutoGenerateColumns="False" IsReadOnly="True">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.Header>
<StackPanel>
<TextBlock Text="Start Date"/>
<DatePicker x:Name="datePickerStart" SelectedDate="{Binding StartDate, Mode=TwoWay}"/>
</StackPanel>
</sdk:DataGridTemplateColumn.Header>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding StartDate, StringFormat='{}{0:yyyy-MM-dd}'}"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.Header>
<StackPanel>
<TextBlock Text="End Date"/>
<sdk:DatePicker x:Name="datePickerEnd" SelectedDate="{Binding EndDate, Mode=TwoWay}"/>
</StackPanel>
</sdk:DataGridTemplateColumn.Header>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding EndDate, StringFormat='{}{0:yyyy-MM-dd}'}"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding DataContext.InitializeCommand, ElementName=dataGrid}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</sdk:DataGrid>
在代码中,我们需要添加以下命令来初始化列头中的DatePicker控件:
public ICommand InitializeCommand
{
get
{
if (_initializeCommand == null)
{
_initializeCommand = new RelayCommand(Initialize);
}
return _initializeCommand;
}
}
private void Initialize()
{
var headerStart = dataGrid.Columns[1].Header as StackPanel;
if (headerStart != null)
{
var datePickerStart = headerStart.Children[1] as DatePicker;
if (datePickerStart != null)
{
datePickerStart.SetValue(DatePicker.SelectedDateProperty, StartDate);
}
}
var headerEnd = dataGrid.Columns[2].Header as StackPanel;
if (headerEnd != null)
{
var datePickerEnd = headerEnd.Children[1] as DatePicker;
if (datePickerEnd != null)
{
datePickerEnd.SetValue(DatePicker.SelectedDateProperty, EndDate);
}
}
}
此时,我们已经完成了Silverlight DataGrid中的无代码设置开始和结束日期DatePicker控件的实现。我们可以在代码中使用下面这样的方式来绑定筛选条件:
CollectionViewSource.GetDefaultView(MyDataItems).Filter = new Predicate<object>(item =>
{
var i = (MyDataItem)item;
// 开始日期筛选条件
if (StartDate.HasValue)
{
if (i.StartDate < StartDate.Value)
{
return false;
}
}
// 结束日期筛选条件
if (EndDate.HasValue)
{
if (i.EndDate > EndDate.Value)
{
return false;
}
}
// 其它筛选条件
...
return true;
});
至此,两个示例都已经完成了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于Silverlight DataGrid中无代码设置开始与结束日期DatePicker的实现方法 - Python技术站