简体   繁体   English

(WPF / C#)使用DispatcherTimer进行UI更新循环

[英](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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM