我的ListView上有很多行,上面有日期戳,我想做的就是在几周之间添加一个非常清晰的分隔符,例如行之间的4px彩色线表示下周开始的地方(IE:最后一次)周日排,下周一排第一排)。
由于似乎几乎不可能找到任何这方面的例子,我开始认为这不是那么微不足道的事情?
答案 0 :(得分:0)
您应首先确定与前一个条目相比具有新周的条目。一种方法是我编写一个比较器,将前一个条目的日期与当前条目的日期进行比较:
public class WeekComparer : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length != 2)
{
throw new Exception("Bad values");
}
var prev = values[0] as DateTime?;
// first entry has no predecessor, so the predecessor is not a different week
if (!prev.HasValue)
{
return true;
}
var dt1 = prev.Value;
var dt2 = (DateTime)values[1];
if (Math.Abs((dt1 - dt2).Days) > 7)
{
return false;
}
// assume monday to be the first day of week
var dow1 = (dt1.DayOfWeek + 7 - DayOfWeek.Monday) % 7;
var dow2 = (dt2.DayOfWeek + 7 - DayOfWeek.Monday) % 7;
var result = (dow1 < dow2) == (dt1 < dt2);
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
请注意,此比较器可能不完整。在计算Time
进行比较之前,可能需要剪切Timespan.Days
部分。
然后,您可以ListViewItem.Style
使用Trigger
WeekComparer
的结果RelativeSource PreviousData
。使用<Grid x:Name="grid1">
<Grid.Resources>
<local:WeekComparer x:Key="sameWeekComparer"/>
</Grid.Resources>
<ListView x:Name="lv1" ItemsSource="{Binding}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource sameWeekComparer}">
<Binding Path="MyDate" RelativeSource="{RelativeSource PreviousData}"/>
<Binding Path="MyDate"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="0 4 0 0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView x:Name="gv1">
<GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name"/>
<GridViewColumn DisplayMemberBinding="{Binding MyDate}" Header="MyDate"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
获取上一个项目值,以便与当前项目进行比较:
Red
这将绘制一行,其中日期与前一行的日期不同,BorderBrush
BorderThickness
和Trigger
仅在项目上方绘制边框。您可以在public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<MyDateVM> items = new List<MyDateVM>();
items.Add(new MyDateVM { Name = "Test 1", MyDate = new DateTime(2018, 12, 31) }); // first entry
items.Add(new MyDateVM { Name = "Test 2", MyDate = new DateTime(2019, 1, 6) }); // same week as end of december 2018
items.Add(new MyDateVM { Name = "Test 3", MyDate = new DateTime(2019, 1, 3) }); // changed order of date
items.Add(new MyDateVM { Name = "Test 4", MyDate = new DateTime(2019, 1, 9) }); // new week
items.Add(new MyDateVM { Name = "Test 5", MyDate = new DateTime(2019, 2, 10) }); // long gap, new week
grid1.DataContext = items;
}
}
。
将Grid视为某个窗口的内容。我测试了以下数据:
MyDateVM
<li>
<label class="switchFilterOn">
<input class="firstOnOfInput" type="checkbox" checked>
<span class="sliderOnOrOf round"></span>
</label>
<span class="onOfSpan">SHOW ONLY PROJECT MEMBERS:</span>
</li>
<li>
<label class="switchFilterOn">
<input class="firstOnOfInput" type="checkbox">
<span class="sliderOnOrOf round"></span>
</label>
<span class="onOfSpan">SHOW INACTIVE EMPLOYEES:</span>
</li>
<li>
<div class="input-group">
<select required="" class="filterSelectOptions" name="filterByProfession" id="filterByProfession">
<option>PROFESSION</option>
</select>
</div>
</li>
<li>
<div class="input-group">
<select required="" class="filterSelectOptions" name="filterByType" id="filterByType">
<option>TYPE</option>
<option value="1">INTERNAL</option>
<option value="2">EXTERNAL</option>
</select>
</div>
</li>
<li>
<div class="input-group">
<input type="number" min="0" required class="filterSelectOptions" id="filterByAge">
<small class="ageLabelFilter" for="filterByAge">AGE</small>
</div>
</li>
<li>
<div class="input-group">
<select required="" class="filterSelectOptions" name="filterByGender" id="filterByGender">
<option>GENDER</option>
<option value="M">MALE</option>
<option value="F">FEMALE</option>
</select>
</div>
</li>
只是一个存储项属性的普通数据类。
答案 1 :(得分:0)
实现这一目标的几种简单方法:
您可以使用ListViewGroupCollection
中的ListView
。
e.g:
MyListview.Group[0].Items.Add(TheItem);
可以在Designer视图中添加组(右键单击和编辑组等)。
或者,您也可以添加一个虚拟行作为分隔符并覆盖颜色和外观(TheItem.BackgroundColor = xxx
)。
答案 2 :(得分:0)
首先,让每个对象返回它们落入哪个星期。我用Google搜索了,所以可能需要更改。
public property int WeekNumber { get { return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear( SomeDate, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday); } }
接下来,为您的资源添加一个组样式。这可以控制它的外观。我把它放在UserControl / Window中:
<DataTemplate x:Key="DateSeparator">
<Border BorderThickness="0,1,0,0" BorderBrush="Black" VerticalAlignment="Center" />
</DataTemplate>
在ListView中引用该样式:
<ListView ...>
<ListView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource DateSeparator}" />
</ListView.GroupStyle>
</ListView>
最后,在代码中,获取其默认集合并设置其分组属性:
var view = CollectionViewSource.GetDefaultView( YourBoundList );
view.GroupDescriptions.Add( new PropertyGroupDescription( "WeekNumber" ) );
设置分组也可以从XAML而不是代码中完成:
<CollectionViewSource x:Key="GroupedDataSource" Source="{Binding YourBoundList}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="WeekNumber" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
...
<ListView ItemsSource="{Binding Source={StaticResource GroupedDataSource}" ...></ListView>
我更喜欢在代码中设置它,因为我可以在运行时操作过滤,排序和/或分组。