[英](WPF/C#) UI updating loop with DispatcherTimer
I have an application where I have a View with several interactive UI elements. 我有一个应用程序,其中有一个包含多个交互式UI元素的View。 In addition, I have a DispatcherTimer running updates to the UI every 10 seconds. 另外,我有一个DispatcherTimer每10秒运行一次UI更新。 I have made a custom dynamic grid that arranges the child elements differently based on how many children the dynamic grid has. 我制作了一个自定义的动态网格,它根据动态网格有多少个子元素来不同地排列子元素。
However, I have an issue. 但是,我有一个问题。 When the timer fires the Dynamic Grid get stuck in a loop when updating the elements, and I am not sure why. 当计时器触发时,动态网格在更新元素时陷入循环,我不确定为什么。 Here is a simplified version of the code, be sure to tell me if it is insufficient: 这是代码的简化版本,请务必告诉我它是否不足:
MainWindow.xaml.cs MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
main = new MainView(pollCollectionMain);
RefreshTimer = new DispatcherTimer();
RefreshTimer.Tick += new EventHandler(OnTimedEvent);
RefreshTimer.Interval = new TimeSpan(0, 0, 10);
RefreshTimer.Start();
}
private void OnTimedEvent(object sender, EventArgs e)
{
//The Polling class has a variable output
pollObj = new Polling();
pollCollectionMain = pollObj.PollingCollection;
main = new MainView(pollCollectionMain);
}
main.cs main.cs
public MainView(ObservableCollection<PollingData> pollLocal)
{
dynGrid = new DynamicGrid();
p = pollLocal;
for (int i = 0; i < p.Count; i++)
{
//Making some new controls
//ControlGrid is just a Grid with mouse functionality
mainControlGrid = new ControlGrid();
mainControlGrid.Children.Add(someControl);
dynGrid.Children.Add(mainControlGrid);
}
}
DynamicGrid(), where an infinite loop happens DynamicGrid(),发生无限循环
public DynamicGrid()
{
_currentChildrenCount = 0;
//The following is the infinite loop
LayoutUpdated += (s, e) =>
{
if (Children?.Count != _currentChildrenCount)
{
_currentChildrenCount = (Children != null) ? Children.Count : 0;
OnNumberOfItemsChangedImpl();
}
};
}
You should not manage layout like this in WPF. 您不应该在WPF中管理这样的布局。 WPF has a built-in way of managing this: Using a Panel. WPF具有一种内置的管理方式:使用面板。
public class YourPanel : Panel {
protected override Size MeasureOverride(Size availableSize) {
if (InternalChildren.Count == 0) return new Size(0, 0);
//Measure each children's size and then compute and return the size the panel needs to display correctly
foreach(UIElement children in InternalChildren) {
children.Measure(sizeYouWantToGiveToTheElement);
}
return totalSizeYourPanelNeeds;
}
protected override Size ArrangeOverride(Size finalSize) {
if (InternalChildren.Count == 0) return new Size(0, 0);
//Arrange each element in the panel according to your own rules
for (int i = 0; i < InternalChildren.Count; i++) {
UIElement children = InternalChildren[i];
//Arrange the panel's children at the position you want and with the size you want
children.Arrange(new Rect(childrenPosition, childrenSize));
}
return finalSize;
}
}
Unless you do this, you'll make needless updates and disturb the dispatcher. 除非您这样做,否则将进行不必要的更新并打扰调度程序。
You can the use your panel in an ItemsControl: 您可以在ItemsControl中使用面板:
<ItemsControl ItemsSource="{Binding Path=YourItems, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<YourPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
You can find more information on custom panels here or here for example. 您可以在此处或此处找到有关自定义面板的更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.