【发布时间】:2019-07-08 10:18:04
【问题描述】:
我正在尝试对一组行进行数据绑定,并对它们执行排序功能,并在排序完成后更新 UI(希望显示排序算法的差异)。
我有一个基本的 WPF 应用程序,它由一个绑定到对象集合的 ItemsControl 组成。这些对象在第一次渲染屏幕的时候是正确绑定的,但是排序操作完成后,底层列表已经正确排序了,但是UI没有重绘?
这是我的 XAML
<Grid>
<Button Content="Sort" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="12" MinWidth="80" Click="Button_Click"/>
<ItemsControl x:Name="mainControl" ItemsSource="{Binding Values}" ItemTemplate="{StaticResource LineDataTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter" />
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
有一个xaml数据模板
<DataTemplate x:Key="LineDataTemplate">
<Line X1="{Binding X1}" Y1="{Binding Y1}"
X2="{Binding X2}" Y2="{Binding Y2}"
Stroke="DarkGray" StrokeThickness="3"/>
</DataTemplate>
主数据上下文包含此 Line 对象的列表
public class Line
{
public int X1 { get; set; }
public int Y1 { get; set; }
public int X2 { get; set; }
public int Y2 { get; set; }
}
当初始化数据上下文时,我会创建一些随机行
private void RandomiseLines()
{
var rnd = new Random();
var startingPoint = 2;
Values = new List<Line>();
for (int i = 0; i < 3; i++)
{
Values.Add(new Line() { X1 = startingPoint, Y1 = 420, X2 = startingPoint, Y2 = (420 - rnd.Next(1, 300)) });
startingPoint += 4;
}
}
然后我在 UI 上有一个按钮,它调用并(现在)使用 linq 调用基本排序
Values = Values.OrderBy(x => x.Y2).ToList();
保存此列表的数据上下文实现了 INotifiedProperty 已更改接口,一旦对列表进行排序,我就会调用 Property changed 事件。尽管底层列表已排序,但 UI 似乎没有重绘,但我尝试使用 ObservableCollection 并包装在 Dispatcher 中,但似乎没有引发任何绑定错误或异常。谁能解释一下为什么没有更新?
编辑:添加预期结果 预期的结果将是 ItemsControl 重绘本身,并且行将采用新的排序顺序
【问题讨论】:
-
排序的预期效果是什么?不是所有的线条都在画布中绘制吗?空的 ItemContainerStyle 的用途是什么?
-
你是否为 Values 属性实现了 INotifyPropertyChanged? IE。它的 setter 会触发 PropertyChanged 事件吗?
-
谢谢,我已经更新了原始问题,但本质上我希望这些线条按顺序重新绘制。 DataContext 还实现了 NotifyPropertyChanged 接口。再次感谢
-
使用 ObservableCollection 代替 List
-
Values setter 会触发 PropertyChanged 事件吗? “排序顺序”是指画布中的堆叠(即 z)顺序?
标签: c# wpf data-binding