2017-08-04 17 views
-1

いくつかのオブジェクトに基づいて動的なUIを作成しています。レンダリングするアイテムが多数あるため、読み込みに時間がかかります。 XML下記参照: -wpfコンテナグリッド内のコントロールの読み込みが遅い

<ScrollViewer Grid.Row="2" ZoomMode="Enabled" x:Name="scrollviewer" 
     VirtualizingStackPanel.VirtualizationMode="Recycling" 
     HorizontalScrollMode="Auto" 
     VerticalScrollMode="Auto" 
     VerticalSnapPointsType="None" 
     HorizontalSnapPointsType="None" 
     HorizontalScrollBarVisibility="Auto" 
     VerticalScrollBarVisibility="Auto" 
     MinZoomFactor="1" IsDoubleTapEnabled="True" 
     RenderTransformOrigin="0,0"> 
     <Grid Background="#FFDDE6EB" x:Name="mygrid" VerticalAlignment="Center" HorizontalAlignment="Center"> 

     </Grid> 
    </ScrollViewer> 

ScrollViewerのは、* 10などの高さと列の内部にあります。動的にアイテムをロードする

コードは以下である: -

public static Grid LoadGridWithItems(Model m) 
     { 

      var grid = new Grid(); 
      grid.UseLayoutRounding = true; 
      grid.RowDefinitions.Clear(); 
      grid.ColumnDefinitions.Clear(); 

      int count = m.Rows; 
      for (int i = 0; i < count; i++) 
      { 
       grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); 
      } 

      count = m.Columns; 
      for (int i = 0; i < count; i++) 
      { 
       grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(m.GetColumnWidth(i), GridUnitType.Star) }); 
      } 
      foreach (Control control in m.Controls) 
      { 
      UIElement uicontrol=null; 
       if (control.Type != null) 
       { 

        switch (control.Type.ToLower()) 
        { 
         case "textbox": 
          uicontrol=new TextBox(); 
          break; 
         case "label": 
          uicontrol = new Label();; 
          break; 

         //bunch of other custom controls 
        } 
        } 


       grid.Children.Add(uicontrol); 
      } 
      return grid; 
     } 

この生成されたグリッドは、次いで、上記XAMLで定義された「mygrid」の子として追加されます。時にはアイテムが5000以上で、ロードに約20〜25秒かかります。 このシナリオをより良い方法で実装する方法に関する提案はありますか?

ありがとうございます!

+1

あなたはMVVMを使用していない理由は、任意の理由は?あなたの要求が許せば 'ListView'を' Virtualization'で使うことができます。つまり、表示されたときにのみアイテムを作成するということです。それは、5000の代わりに100個の項目をレンダリングするので、大幅なパフォーマンスの向上になります。 – XAMlMAX

+0

mvvmを使用できないのは、各行に異なるコントロールの組み合わせがあり、したがって使用できる単一のデータテンプレートがないという唯一の理由です。グリッドに追加されたコントロールは、 'コントロール'クラスのプロパティにバインドされますが、各行に対して異なるテンプレートを生成する方法がわかりません。 – AjS

+0

'TemplateSelector'を見て、どのテンプレートを適用するかを選択することができます。また、コンテナを' ListView'に変更すると、 'Virtualization'の前に使用することができます。 – XAMlMAX

答えて

0

ItemsControlおよびMVVMを使用すると、コードの品質と可読性が向上します。さらに、パフォーマンスが向上すると思います。このようなもの:

また、ユーザーがフォームに紹介する値を取得する方が簡単です。モデルクラスのプロパティに値をバインドすることができます。

public class TextControl 
{ 
    public string TextValue { get; set; } 
} 

<DataTemplate DataType="{x:Type yourNameSpace:TextControl}"> 
    <TextBox Text="{Binding TextValue}" /> 
</DataTemplate> 

編集。サンプル:

XAML:

<Window x:Class="WpfApplication2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication2" 
    Title="MainWindow" Height="350" Width="525"> 
<ItemsControl ItemsSource="{Binding List}"> 
    <ItemsControl.Resources> 
     <DataTemplate DataType="{x:Type local:ControlText}"> 
      <StackPanel Orientation="Horizontal" Background="Yellow"> 
       <TextBlock Text="{Binding Label}" /> 
       <TextBlock Text="{Binding Text}" /> 
      </StackPanel> 
     </DataTemplate> 

     <DataTemplate DataType="{x:Type local:ControlBool}"> 
      <StackPanel Orientation="Horizontal" Background="Orange"> 
       <TextBlock Text="{Binding Label}" /> 
       <CheckBox IsChecked="{Binding Value}" /> 
      </StackPanel> 
     </DataTemplate> 

    </ItemsControl.Resources> 
</ItemsControl> 

CS:

using System; 
using System.Collections.Generic; 
using System.Windows; 

namespace WpfApplication2 
{ 
public partial class MainWindow : Window 
{ 
    public IEnumerable<Control> List { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 

     DataContext = this; 

     var l = new List<Control>(); 
     l.Add(new ControlText() { Text = "Michael", Label = "Name" }); 
     l.Add(new ControlBool() { Value = true, Label = "C#" }); 
     l.Add(new ControlBool() { Value = false, Label = "WPF" }); 
     l.Add(new ControlText() { Text = "Martinez", Label= "Surname" }); 

     List = l; 
    } 
} 

public abstract class Control 
{ 
    public String Label { get; set; } 
} 

public class ControlText : Control 
{ 
    public String Text { get; set; } 
} 

public class ControlBool : Control 
{ 
    public Boolean Value { get; set; } 
} 
} 

:D

+0

各行には異なるコントロールの組み合わせがあるため、単一のデータテンプレートを使用できないため、この方法でコンテナグリッドのコンテンツを動的に生成しています。 – AjS

+0

コレクションにあるオブジェクトの種類ごとに1つずつ、複数のDataTemplateを持つことができます。 – Lamelas84

+0

申し訳ありませんが、ItemsControlでDataTemplateを1つのテンプレートにのみ設定できます。その特定のテンプレートはItemsControl内のすべての行に適用されます。 ItemsControlで複数のテンプレートをどこに、どのように設定できますか? – AjS

関連する問題