视图之间切换缓慢(视图包含包含许多项目的数据网格)

发布于 2024-11-28 12:01:05 字数 6822 浏览 1 评论 0原文

我使用 Caliburn Micro &我的 WPF 应用程序中基于 .NET 4.0 的 Fluent Ribbon。我的问题是视图之间的更改太慢。我想我知道这个问题的根源。

但我不知道如何解决。首先我描述一下我的应用程序的设计。

Shell 是 WPF 窗口,它包含 Fluent Ribbon.Menu 和 RibbonTabItem 项。如果用户单击 shell 中的选项卡项,则会加载新视图。

这是视图的 XAML:

    <StackPanel Grid.Row="0">
        <Fluent:Ribbon>
            <Fluent:Ribbon.Menu>

                <Fluent:Backstage>
                    <Fluent:BackstageTabControl>
                        <Fluent:BackstageTabItem Header="Open"/>
                        <Fluent:BackstageTabItem Header="Close"/>
                    </Fluent:BackstageTabControl>
                </Fluent:Backstage>

            </Fluent:Ribbon.Menu>

            <!--Tabs-->
            <Fluent:RibbonTabItem Micro:Message.Attach="[PreviewMouseLeftButtonDown]=[Action ShowView1()]"/>
    <Fluent:RibbonTabItem Micro:Message.Attach="[PreviewMouseLeftButtonDown]=[Action ShowView2()]"/>
    <Fluent:RibbonTabItem Micro:Message.Attach="[PreviewMouseLeftButtonDown]=[Action ShowViewN()]"/>

        </Fluent:Ribbon>

    </StackPanel>

    <Grid Grid.Row="1">
        <ContentControl x:Name="ActiveItem" />
    </Grid>
</Grid>

ShellView 模型类:

namespace T_TOOL.ViewModels
{

    public interface IShellViewModel{}

    [Export(typeof(IShellViewModel))]
    public class ShellViewModel :Conductor<IScreen>.Collection.OneActive,
        IShellViewModel, 
        IPartImportsSatisfiedNotification
    {

        public void ShowView1()
        {
            var screen = IoC.Get<IShowView1();
            ActivateItem(screen);
        }

        public void ShowView2()
        {
            var screen = IoC.Get<IShowView2();
            ActivateItem(screen);
        }

//...
        public void ShowViewN()
        {
            var screen = IoC.Get<IShowViewN();
            ActivateItem(screen);
        }

    }
}

ViewModel1、ViewModel2、...ViewModelN 仅包含 DataGrid 控件。在 Datagrid 控件上,我从视图模型绑定 ICollectionView 的属性类型。

该属性包含 18 000 - 25 000 件物品。我认为这是问题的根源,为什么视图之间的更改很慢。我使用扩展 WPF 工具包中的 DataGrid 控件。

我将 DataGrid 的 EnableRowVirtualization 和 EnableColumnVirtualization 属性设置为 true。但这没有帮助。

这是 ViewModel1 的 View XAML 代码:

    <Style x:Key="MainView_CallsDataGrid" TargetType="{x:Type Controls:DataGrid}" 
           BasedOn="{StaticResource MainView_FontBaseStyle}">
        <Setter Property="AutoGenerateColumns" Value="False"/>
        <Setter Property="VerticalScrollBarVisibility" Value="Visible"/>
        <Setter Property="HorizontalScrollBarVisibility" Value="Visible"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="Margin" Value="4,15,4,15"/>
        <Setter Property="EnableRowVirtualization" Value="True"/>
        <Setter Property= "EnableColumnVirtualization" Value="True"/>
    </Style>

        <Controls:DataGrid.Columns>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Number}"
                                         Header="Cell phone No"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=CallType}"
                                         Header="Call type"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Dt}"
                                         Header="Date / Time"/>


            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=CallingNumber}"
                                         Header="Calling Number"/>


            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=VoiceNetwork}"
                                         Header="Voice network"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Type}"
                                         Header="Type"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=TalkTime}"
                                         Header="Talk time"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Price}"
                                         Header="Price"/>

        </Controls:DataGrid.Columns>

ViewModel1 类的代码:

        public ICollectionView CallsView
        {
            get
            {
                return _callsView;
            }
            set
            {
                _callsView = value;
                NotifyOfPropertyChange(() => CallsView);
            }
        }

//... Init CallsView property from List<T> property

       CallsView = CollectionViewSource.GetDefaultView(List<T>);
       FilterCalls();
       CallsView.Refresh();

//Filter method
        private void FilterCalls()
        {
            if (CallsView != null)
            {
                CallsView.Filter = new Predicate<object>(FilterOut);
                CallsView.Refresh();
            }
        }

我的观点是正确的吗?视图之间的切换很慢,因为数据网格包含很多行?或者问题是我绑定在 ICollectionView 的 DataGrid 控件属性类型上?

感谢您的意见、建议和反馈。

这是屏幕截图

屏幕截图

I use Caliburn Micro & Fluent Ribbon in my WPF app based on .NET 4.0. My problem is that change between views is too slow. I think that I know root of this problem.

But I don’t how to solve. So first I describe design of my app.

Shell is WPF window and it contains Fluent Ribbon.Menu with RibbonTabItem items. If user click on tab item in shell is loaded new view.

Here is XAML of view:

    <StackPanel Grid.Row="0">
        <Fluent:Ribbon>
            <Fluent:Ribbon.Menu>

                <Fluent:Backstage>
                    <Fluent:BackstageTabControl>
                        <Fluent:BackstageTabItem Header="Open"/>
                        <Fluent:BackstageTabItem Header="Close"/>
                    </Fluent:BackstageTabControl>
                </Fluent:Backstage>

            </Fluent:Ribbon.Menu>

            <!--Tabs-->
            <Fluent:RibbonTabItem Micro:Message.Attach="[PreviewMouseLeftButtonDown]=[Action ShowView1()]"/>
    <Fluent:RibbonTabItem Micro:Message.Attach="[PreviewMouseLeftButtonDown]=[Action ShowView2()]"/>
    <Fluent:RibbonTabItem Micro:Message.Attach="[PreviewMouseLeftButtonDown]=[Action ShowViewN()]"/>

        </Fluent:Ribbon>

    </StackPanel>

    <Grid Grid.Row="1">
        <ContentControl x:Name="ActiveItem" />
    </Grid>
</Grid>

ShellView model class:

namespace T_TOOL.ViewModels
{

    public interface IShellViewModel{}

    [Export(typeof(IShellViewModel))]
    public class ShellViewModel :Conductor<IScreen>.Collection.OneActive,
        IShellViewModel, 
        IPartImportsSatisfiedNotification
    {

        public void ShowView1()
        {
            var screen = IoC.Get<IShowView1();
            ActivateItem(screen);
        }

        public void ShowView2()
        {
            var screen = IoC.Get<IShowView2();
            ActivateItem(screen);
        }

//...
        public void ShowViewN()
        {
            var screen = IoC.Get<IShowViewN();
            ActivateItem(screen);
        }

    }
}

ViewModel1, ViewModel2, ...ViewModelN contains only DataGrid controls. On Datagrid control I bind property type of ICollectionView from view model.

This property contains 18 000 - 25 000 items. I think this is root of problem why is change between Views is slow. I use DataGrid Control from Extended WPF Toolkit.

I set EnableRowVirtualization and EnableColumnVirtualization properties of DataGrid on true. But it doesn’t help.

Here is View XAML code of ViewModel1:

    <Style x:Key="MainView_CallsDataGrid" TargetType="{x:Type Controls:DataGrid}" 
           BasedOn="{StaticResource MainView_FontBaseStyle}">
        <Setter Property="AutoGenerateColumns" Value="False"/>
        <Setter Property="VerticalScrollBarVisibility" Value="Visible"/>
        <Setter Property="HorizontalScrollBarVisibility" Value="Visible"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="Margin" Value="4,15,4,15"/>
        <Setter Property="EnableRowVirtualization" Value="True"/>
        <Setter Property= "EnableColumnVirtualization" Value="True"/>
    </Style>

        <Controls:DataGrid.Columns>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Number}"
                                         Header="Cell phone No"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=CallType}"
                                         Header="Call type"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Dt}"
                                         Header="Date / Time"/>


            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=CallingNumber}"
                                         Header="Calling Number"/>


            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=VoiceNetwork}"
                                         Header="Voice network"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Type}"
                                         Header="Type"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=TalkTime}"
                                         Header="Talk time"/>

            <Controls:DataGridTextColumn IsReadOnly="True"
                                         CellStyle="{StaticResource MainView_CallsDataGrid_CellStyle}"
                                         Binding="{Binding Path=Price}"
                                         Header="Price"/>

        </Controls:DataGrid.Columns>

code from ViewModel1 class:

        public ICollectionView CallsView
        {
            get
            {
                return _callsView;
            }
            set
            {
                _callsView = value;
                NotifyOfPropertyChange(() => CallsView);
            }
        }

//... Init CallsView property from List<T> property

       CallsView = CollectionViewSource.GetDefaultView(List<T>);
       FilterCalls();
       CallsView.Refresh();

//Filter method
        private void FilterCalls()
        {
            if (CallsView != null)
            {
                CallsView.Filter = new Predicate<object>(FilterOut);
                CallsView.Refresh();
            }
        }

My opinion is correct? Switch betweens views is slow because datagrid contains many rows? Or problem is that I bind on DataGrid control property type of ICollectionView?

Thank you for your opinions, suggestions and feedback.

Here is screen shot.

Screen Shot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

早乙女 2024-12-05 12:01:06

我不确定 Ribbon 选项卡是否与 TabControl 选项卡相同,但 TabControl 在不可见时会破坏它的 TabItems。这会导致当您切换到选项卡时重新绘制每个 TabItem,并且具有大量控件的 TabItem 将花费大量时间来重新绘制。

我在使用 TabControl 时遇到了类似的问题,其中切换选项卡会重新绘制整个选项卡,导致切换速度非常慢。我最终使用了所示的代码 此处 扩展 TabControl 并防止它在切换选项卡时破坏其子级。也许您可以使用功能区选项卡执行类似的操作

I'm not positive if the Ribbon tabs are the same as a TabControl tabs, but a TabControl destorys it's TabItems when they're not visible. This causes each TabItem to get re-drawn when you switch to the tab, and a TabItem with a large number of controls will take a noticable amount of time to get redrawn.

I had a similar problem using a TabControl where switching tabs would re-draw the entire tab and it caused switching to be really slow. I ended up using the code shown here that extends the TabControl and prevents it from destorying it's children when switching tabs. Perhaps you can do something similiar with the Ribbon tabs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文