刚做完一个使用了wpf技术的项目,总结一下项目中使用到的一些以前没用过的技术
DataGrid 过滤
nuget库 DataGridExtensions 提供了自定义扩展DataGrid列过滤的方法
根据例子中的MultipleChoiceFilter 可以自定义任意过滤。
我的日期过滤控件:
// xaml:
<Control x:Class= "readLog.Views.Filters.DateFilter"
x:Name= "Control"
xmlns= "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x= "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc= "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d= "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local= "clr-namespace:readLog.Views.Filters"
xmlns:dgx= "urn:tom-englert.de/DataGridExtensions"
xmlns:sys= "clr-namespace:System;assembly=mscorlib"
mc:Ignorable= "d"
d:DesignHeight= "30" d:DesignWidth= "30"
>
<Control.Resources>
<ObjectDataProvider x:Key= "dateTypeEnum" MethodName= "GetValues"
ObjectType= "{x:Type sys:Enum}" >
<ObjectDataProvider.MethodParameters>
<x:Type TypeName= "local:DateFilterType" ></x:Type>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Control.Resources>
<Control.Template>
<ControlTemplate>
<Grid>
<ToggleButton x:Name= "ToggleButton" >
<StackPanel Orientation= "Horizontal" >
<TextBlock x:Name= "IsFilterActiveMarker" Text= "." Margin= "0,0,-4,0" Foreground= "{Binding ElementName=FilterSymbol, Path=Foreground}" FontWeight= "Bold" />
<Control x:Name= "FilterSymbol" Style= "{DynamicResource {x:Static dgx:DataGridFilter.IconStyleKey}}" />
</StackPanel>
</ToggleButton>
<Popup
DataContext= "{Binding ElementName=Control}"
x:Name= "Popup" IsOpen= "{Binding Path=IsChecked, ElementName=ToggleButton, Mode=TwoWay}"
AllowsTransparency= "True" StaysOpen= "False" >
<StackPanel>
<ComboBox x:Name= "typeBox"
ItemsSource= "{Binding Source={StaticResource dateTypeEnum}}"
SelectedItem= "{Binding Path=FilterType}" />
<DatePicker x:Name= "begTm"
Visibility= "{Binding Path=BeginTimeVisible}"
SelectedDate= "{Binding Path=BeginTime}"
/>
<DatePicker x:Name= "endTm"
Visibility= "{Binding Path=EndTimeVisible}"
SelectedDate= "{Binding Path=EndTime}"
/>
</StackPanel>
</Popup>
</Grid>
</ControlTemplate>
</Control.Template>
</Control>
// 交互
/// <summary>
/// DateFilter.xaml 的交互逻辑
/// </summary>
public partial class DateFilter : Control
{
public DateFilter ( )
{
InitializeComponent();
}
# region dependency property
public static readonly DependencyProperty FilterTypeProperty = DependencyProperty.Register(
"FilterType" , typeof (DateFilterType), typeof (DateFilter),
new FrameworkPropertyMetadata( default (DateFilterType), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (s, e) => ((DateFilter)s).FilterTypeChange()));
private void FilterTypeChange ( )
{
// 可见性
switch (FilterType)
{
case DateFilterType.All:
case DateFilterType.ThisYear:
case DateFilterType.ThisMonth:
case DateFilterType.PreYear:
case DateFilterType.PreMonth:
BeginTimeVisible = Visibility.Collapsed;
EndTimeVisible = Visibility.Collapsed;
break ;
case DateFilterType.Earlier:
BeginTimeVisible = Visibility.Collapsed;
EndTimeVisible = Visibility.Visible;
break ;
case DateFilterType.Later:
BeginTimeVisible = Visibility.Visible;
EndTimeVisible = Visibility.Collapsed;
break ;
case DateFilterType.Between:
BeginTimeVisible = Visibility.Visible;
EndTimeVisible = Visibility.Visible;
break ;
default :
throw new ArgumentOutOfRangeException();
}
RangeChanged();
}
private void RangeChanged ( )
{
Filter = new ContentFilter(FilterType, BeginTime, EndTime);
}
public DateFilterType FilterType
{
get => (DateFilterType) GetValue(FilterTypeProperty);
set => SetValue(FilterTypeProperty, value );
}
public static readonly DependencyProperty FilterProperty = DependencyProperty.Register(
"Filter" , typeof (ContentFilter), typeof (DateFilter),
new FrameworkPropertyMetadata( default (ContentFilter), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (s, e) => ((DateFilter)s).FilterChanged()));
public ContentFilter Filter
{
get => (ContentFilter) GetValue(FilterProperty);
set => SetValue(FilterProperty, value );
}
private void FilterChanged ( )
{
var filter = Filter as ContentFilter;
if ( null == filter)
{
return ;
}
FilterType = filter.FilterType;
BeginTime = filter.BeginTime;
EndTime = filter.EndTime;
}
public static readonly DependencyProperty BeginTimeProperty = DependencyProperty.Register(
"BeginTime" , typeof (DateTime), typeof (DateFilter),
new FrameworkPropertyMetadata(DateTime.Today, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,(s, e) => ((DateFilter)s).RangeChanged()));
public DateTime BeginTime
{
get => (DateTime) GetValue(BeginTimeProperty);
set => SetValue(BeginTimeProperty, value );
}
public static readonly DependencyProperty EndTimeProperty = DependencyProperty.Register(
"EndTime" , typeof (DateTime), typeof (DateFilter),
new FrameworkPropertyMetadata(DateTime.Today, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,(s, e) => ((DateFilter)s).RangeChanged()));
public DateTime EndTime
{
get => (DateTime) GetValue(EndTimeProperty);
set => SetValue(EndTimeProperty, value );
}
public static readonly DependencyProperty PropertyTypeProperty = DependencyProperty.Register(
"BeginTimeVisible" , typeof (Visibility), typeof (DateFilter),
new FrameworkPropertyMetadata(Visibility.Collapsed, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (s, e) => ((DateFilter)s).RangeChanged()));
public Visibility BeginTimeVisible
{
get => (Visibility) GetValue(PropertyTypeProperty);
set => SetValue(PropertyTypeProperty, value );
}
public static readonly DependencyProperty EndTimeVisibleProperty = DependencyProperty.Register(
"EndTimeVisible" , typeof (Visibility), typeof (DateFilter),
new FrameworkPropertyMetadata(Visibility.Collapsed, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (s, e) => ((DateFilter)s).RangeChanged()));
public Visibility EndTimeVisible
{
get => (Visibility) GetValue(EndTimeVisibleProperty);
set => SetValue(EndTimeVisibleProperty, value );
}
# endregion
public class ContentFilter : IContentFilter
{
public ContentFilter ( DateFilterType type, DateTime beg, DateTime end )
{
FilterType = type;
BeginTime = beg;
EndTime = end;
}
public bool IsMatch ( object value )
{
if ( null == value )
{
return false ;
}
try
{
var tm = (DateTime) value ;
switch (FilterType)
{
case DateFilterType.All:
return true ;
case DateFilterType.ThisYear:
return IsMatchYear(tm, DateTime.Today);
case DateFilterType.ThisMonth:
return IsMatchMonth(tm, DateTime.Today);
case DateFilterType.PreYear:
return IsMatchYear(tm, DateTime.Today.AddYears( -1 ));
case DateFilterType.PreMonth:
return IsMatchMonth(tm, DateTime.Today.AddMonths( -1 ));
case DateFilterType.Earlier:
return tm.Date <= EndTime.Date;
case DateFilterType.Later:
return tm.Date >= BeginTime.Date;
case DateFilterType.Between:
return IsMatchDate(tm, BeginTime, EndTime);
default :
throw new ArgumentOutOfRangeException();
}
}
catch (Exception e)
{
return false ;
}
}
public DateFilterType FilterType { get ; }
public DateTime BeginTime { get ; }
public DateTime EndTime { get ; }
# region Datetime
private bool IsMatchMonth ( DateTime tm, DateTime toMatch )
{
return IsMatchDate(tm, GetFirstDayOfMonth(toMatch), GetLastDayOfMonth(toMatch));
}
private bool IsMatchDate ( DateTime tm, DateTime beg, DateTime end )
{
tm = tm.Date;
return tm <= beg && tm >= end;
}
private bool IsMatchYear ( DateTime tm, DateTime toMatch )
{
return IsMatchDate(tm, GetLastDayOfYear(toMatch), GetFirstDayOfYear(toMatch));
}
private DateTime GetFirstDayOfMonth ( DateTime dt )
{
var dtFrom = dt;
dtFrom = dtFrom.AddDays(-(dtFrom.Day - 1 ));
return dtFrom;
}
private DateTime GetLastDayOfMonth ( DateTime dt )
{
var dtTo = dt;
dtTo = dtTo.AddMonths( 1 );
dtTo = dtTo.AddDays(-(dtTo.Day));
return dtTo;
}
private DateTime GetFirstDayOfYear ( DateTime dt )
{
var dtFrom = dt;
dtFrom = dtFrom.AddMonths(-(dtFrom.Month - 1 ));
return GetFirstDayOfMonth(dtFrom);
}
private DateTime GetLastDayOfYear ( DateTime dt )
{
var dtTo = dt;
dtTo = dtTo.AddYears( 1 );
dtTo = dtTo.AddMonths(-dt.Month);
return GetLastDayOfMonth(dtTo);
}
# endregion
}
}
[TypeConverter( typeof (EnumDescriptionTypeConverter))]
public enum DateFilterType
{
[Description( "所有" )]
All, // 全部
[Description( "今年" )]
ThisYear,
[Description( "本月" )]
ThisMonth,
[Description( "去年" )]
PreYear,
[Description( "上个月" )]
PreMonth,
[Description( "指定日期以前" )]
Earlier,
[Description( "指定日期以后" )]
Later,
[Description( "之间" )]
Between,
}
枚举显示
枚举显示有两个方案,
- 转换器, 在xaml中定义一个转换器资源
- 定义一个用来显示的字符串属性,界面绑定这个字符串属性。
读取DataGrid某一行某一列的值
从控件 DataGridExtensions 中学习到的。拿到的是真实的绑定对象,而不是显示的字符串。一开始用 GetCelllContent(),但对未显示的行无法取到。
class GetCellValueClass : DependencyObject
{
/// <summary>
/// Identifies the CellValue dependency property, a private helper property used to evaluate the property path for the list items.
/// </summary>
private static readonly DependencyProperty _cellValueProperty =
DependencyProperty.Register( "_cellValue" , typeof ( object ), typeof (GetCellValueClass));
public object GetCellValue ( DataGridColumn col, object item )
{
var propertyPath = col.SortMemberPath;
if ( string .IsNullOrEmpty(propertyPath))
return null ;
BindingOperations.SetBinding( this , _cellValueProperty, new Binding(propertyPath) { Source = item });
var propertyValue = GetValue(_cellValueProperty);
BindingOperations.ClearBinding( this , _cellValueProperty);
return propertyValue;
}
}
使用方法:
new GetCellValueClass().GetCellValue(col, item);
- 打赏
- 分享
分享到...
请选择打赏方式
- 微信
- 支付宝