WPF快速控件/任何创建

WPF快速控件/任何创建,wpf,performance,Wpf,Performance,我有一个itemcontrol,它有3个可能的数据模板 <DataTemplate> <StackPanel> <TextBlock FontSize="25" FontWeight="Light" Margin="0,8,0,5" Text="{Binding Name}" > </TextBlock>

我有一个itemcontrol,它有3个可能的数据模板

<DataTemplate>

    <StackPanel>

        <TextBlock
            FontSize="25"
            FontWeight="Light"
            Margin="0,8,0,5"
            Text="{Binding Name}" >
        </TextBlock>
        <!-- Εδω τα items -->

        <ContentControl
            Content="{Binding Preferences}"
            Name="items" >
        </ContentControl>
    </StackPanel>

    <DataTemplate.Triggers>

        <DataTrigger
            Binding="{Binding Path=SelectionMode}"
            Value="1" >

            <Setter
                Property="ContentTemplate"
                TargetName="items"
                Value="{StaticResource SoloSelection}" />
        </DataTrigger>

        <DataTrigger
            Binding="{Binding Path=SelectionMode}"
            Value="2" >

            <Setter
                Property="ContentTemplate"
                TargetName="items"
                Value="{StaticResource MultiSelection}" />
        </DataTrigger>

        <DataTrigger
            Binding="{Binding Path=SelectionMode}"
            Value="3" >

            <Setter
                Property="ContentTemplate"
                TargetName="items"
                Value="{StaticResource MultiQuantitySelection}" />
        </DataTrigger>
    </DataTemplate.Triggers>

</DataTemplate>

里面的东西是一个带纽扣的包裹。所以虚拟化看起来并不容易。我想要平滑的滚动。问题是,尽管按钮是边框和文本块,但速度很慢

我做了一个测试

var sw = new Stopwatch();
sw.Start();
var vv = new SolidColorBrush(Colors.Red);
for (int i = 0; i < 150; i++)
{
    // here is the operation that fills the control
    var b = new Button();
    b.Height = 65;
    b.Width = 120;
    b.Content = "Gamiese";
    this.items.Items.Add(b);
}


this.Dispatcher.BeginInvoke(
        DispatcherPriority.Loaded,
        new Action(() =>
        {
            sw.Stop();
            MessageBox.Show("Took " + sw.ElapsedMilliseconds + " ms");
        }));
}
var sw=新秒表();
sw.Start();
var vv=新的SolidColorBrush(颜色为红色);
对于(int i=0;i<150;i++)
{
//下面是填充控件的操作
var b=新按钮();
b、 高度=65;
b、 宽度=120;
b、 Content=“Gamiese”;
本.项目.项目.添加(b);
}
this.Dispatcher.BeginInvoke(
DispatcherPriority.已加载,
新操作(()=>
{
sw.Stop();
MessageBox.Show(“take”+sw.elapsedmillyses+“ms”);
}));
}
这在我的电脑上大约需要40-50毫秒,但在慢速电脑上需要200毫秒以上。因此,与所有其他材料,而不是这个简单的例子,它可以高达600-900毫秒。所以触摸体验可能是缓慢而痛苦的。我把这归咎于WPF,因为我用QtQML做了一个类似的测试,并为更重的200个按钮创建了一个类似的测试,它是即时点亮的,并且具有平滑的滚动。因此,WPF在这方面的开箱即用表现并不好。有什么我能做的吗?甚至缓存按钮也没有帮助,因为填充树似乎是个问题。渲染不是问题,因为在所有计算机上滚动都非常快。。
自定义绘图可能会解决我的问题,但我为什么要这样做

您的UI方案可能需要重新设计。从我从你的帖子(这不是很清楚)收集到的信息来看,你试图在stackpanel中堆叠一堆按钮

你在低速机器上的测试显示1.25ms/button,这听起来很不错。。。除非你滥用这个系统

更好的方法是使自己成为一个ListView,并将感兴趣的项添加为项,这样您就可以让ListView的虚拟化决定何时实例化UI元素


您的测试表明,您正在尝试堆积超过9000像素高的按钮,这对于具有超高分辨率的超大屏幕也没有意义。

也许您应该为这两个测试发布完整的可编译代码;目前,在WPF方面,您正在谈论一个
ItemControl
,您正在显示一个
DataTemplate
,但是演示代码完全不相关(普通按钮)。对于普通按钮,我无法重现您的问题,在达到200毫秒的总时间(从构造函数调用到
ContentRendered
)之前,我最多有1000个按钮。另外,Button并不是一个轻量级的对象,尝试使用
TextBlock
可以在200毫秒的总时间内创建2500个对象。我将添加更多细节。200毫秒是在使用atom cpu和普通按钮的慢速计算机上。我注意到,当我制作自定义控件时,OnRender被称为“即使控件不可见”,您应该提供静态资源,也许还可以提供一些关于您正在做什么的进一步信息。看起来您正在使用mvvm是因为您的绑定,但是如果我们没有获得您的VM或您绑定到的其他内容,我们无法帮助您。如果元素进入视图,通常会动态创建视图元素,如果我提醒正确,视图也会重新使用。如果在
列表框中只看到3个项目,那么无论
项目资源中有多少元素,都将只有3个视图元素?听起来很合理。很有可能你的UI设计需要彻底修改——反正没有人愿意在屏幕上看到150个按钮(你是在实施扫雷吗?)我不需要那么多,但它们可以是70个按钮,用于POS应用程序。因此,atom cpuI上的速度可能会很慢。我也在构建POS,我可以肯定地告诉你,你不需要同时显示70个按钮。有些程序有70个首选项,例如显示为按钮。我见过的其他程序在一个屏幕上有更多按钮。仅仅因为有人这样做并不意味着没错。曾经有一家以拥有全键盘而自豪的电话公司,因为生产少于10个按键的电话的公司已经将其消灭。如果你想在没有技术部分的UX上发布这个问题,问一下如何组织界面,使其不需要70个按钮,你会感到惊讶。