减慢绑定更新?

时间:2014-08-21 02:58:20

标签: c# wpf xaml binding

我的应用包含许多ListBox。每个ListBox包含许多ListBoxItem。我想要强制执行的是,ListBoxItem的MaxWidth始终是ListBox宽度的80%。目前,我这样绑定它:

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="MaxWidth" Value="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource MessageWidthConverter}}"/>

它可以工作,但不幸的是它使应用程序的大小非常缓慢。在重新调整大小的过程中,i7 2600的CPU使用率超过了50%,我理解这是由于数千个ListBoxItem的新MaxWidth的大量计算所致。

有没有办法在不调整大小的过程中造成巨大的减速,或以任何方式要求绑定不经常更新?

1 个答案:

答案 0 :(得分:1)

在WinForm中托管Wpf控件时,我们遇到了类似的问题。对我们来说,最好的解决方案是在OnResize Event

中暂停控件的布局
protected override void OnResize(EventArgs e)
{
    // supress flickering if dockstate is float
    if (DockHandler.DockState == WeifenLuo.WinFormsUI.Docking.DockState.Float) {
        WpfInteropHelper.Suspend(this);
    }
    base.OnResize(e);
    if (DockHandler.DockState == WeifenLuo.WinFormsUI.Docking.DockState.Float) {
        WpfInteropHelper.Resume(this);
    }
}

因此我们添加了一个辅助类:

/// <summary>
/// Class containing helper functions for wpf interoperability 
/// </summary>
public static class WpfInteropHelper
{
    private const int WMSETREDRAW = 0x000B;

    /// <summary>
    /// Suspends the specified control.
    /// </summary>
    /// <param name="control">The control.</param>
    public static void Suspend(Control control)
    {
        Message msgSuspendUpdate = Message.Create(control.Handle, WMSETREDRAW, IntPtr.Zero, IntPtr.Zero);

        NativeWindow window = NativeWindow.FromHandle(control.Handle);
        window.DefWndProc(ref msgSuspendUpdate);
    }

    /// <summary>
    /// Resumes the specified control.
    /// </summary>
    /// <param name="control">The control.</param>
    public static void Resume(Control control)
    {
        control.Visible = false;
        var wparam = new IntPtr(1);
        Message msgResumeUpdate = Message.Create(control.Handle, WMSETREDRAW, wparam, IntPtr.Zero);
        NativeWindow window = NativeWindow.FromHandle(control.Handle);
        if (window != null) {
            window.DefWndProc(ref msgResumeUpdate);
        }
        control.Invalidate();
        control.Visible = true;
    }
}

我希望您也可以将它用于WPF控件。