2012-03-15 17 views
0

私のアプリケーションは、すべて1つのウィンドウに表示されている3つの異なるページに移動できます(一度に1つずつ)。同じウィンドウに表示されるすべてのページは、ユーザーコントロールです。動的にボタンをスタイルで作成:指定された要素は、すでに別の要素の論理的な子です。最初に切断する

ボタン「A」をクリックするたびに、新しいボタンが作成され、スタックパネルに追加されます。だから基本的に5回押すと、5つのボタンがお互いの隣にうまく配置されます。 以下のコードは、画面をページBからAに戻します(すでにページBにあると仮定します)。ここでは、保存されたボタンのリストを繰り返し処理するメソッドを呼び出します。

それ短い私は、このウィンドウが再びロードされるときに、私は単純に戻っ値(ボタン)を読み込むことができリストまたは何か他のもので作成されたアイテムを保存したい。

ページBにするために:

private void btnNoProduction_Click(object sender, RoutedEventArgs e) 
{ 
    MainWindow main = new MainWindow(); 

    Switcher.Switch(main);  
    main.reloadDynamicRegistrationContent(); 
} 

ページA(メインウィンドウ)ここでは、保存されたボタンでリストを反復処理します。

public void reloadDynamicRegistrationContent() 
{ 
    for (int i = 0; i < GlobalVar._listReg.Count; i++) 
    { 
     spHorizontal.Children.Add(GlobalVar._listReg[i]); //ERROR Specified Element is already the logical..... 
    } 
} 

私はリスト(これらのボタンを保存する方法のいくつかの並べ替えを必要とするが、私はエラー指定された要素がすでに別の要素の論理的な子で得続ける。それを最初に外します。 WPF。 私がしようとすると、それが失敗しました静的クラスからリストにアクセスするために

コードが動的にボタンを作成するには:。

private void btnTestRegistration_Click(object sender, RoutedEventArgs e) 
{ 
    Button newBtn = new Button(); 
    newBtn.Name = "btnRegistration" + registrationCount.ToString(); 
    newBtn.Width = 151; 
    newBtn.Height = 73; 
    newBtn.Click += new RoutedEventHandler(this.newBtn_Click); 

    Thickness margin = newBtn.Margin; 
    margin.Left = 10; 
    margin.Right = 5; 
    newBtn.Margin = margin; 

    Style style = this.FindResource("ButtonStyleRegistration") as Style; 
    newBtn.Style = style; 

    //force build template 
    newBtn.ApplyTemplate(); 

    var tb = VisualTreeNavigator.FindVisualChild<TextBlock>(newBtn, "tbRegistration1"); 
    tb.Text = "text cause 1 " + registrationCount.ToString(); 

    var tb2 = VisualTreeNavigator.FindVisualChild<TextBlock>(newBtn, "tbRegistration2"); 
    tb2.Text = "text cause 2 " + registrationCount.ToString(); 

    spHorizontal.Children.Add(newBtn); 
    GlobalVar.AddButtonToList(newBtn); 
    registrationCount++; 
} 

をこれまでのところ、すべてが正常に追加されますが、私はそのボタンの束を保存することができません後でこの画面に戻るときはいつでも作成されています。

GlobalVarはリストがある静的なクラスです。ここで私はリストに作成されているすべてのボタンの内容を保存しようとします。

public class GlobalVar 
{ 
    public static List<Button> _listReg = new List<Button>(); 

    public static void AddButtonToList(Button b) 
    { 
     _listReg.Add(b); 
    } 
} 

答えて

1

WPFでは、各UI要素は任意の論理ツリーに1回しか参加できません。 <Button>要素を子として(子プロパティ、子要素、コンテンツプロパティなど)複数回使用することはできません。

MainWindowは削除されていないようです。たとえあなたがそれを処理していても(つまり、MainWindowが範囲外になって閉じてしまったとしても)、コードからはわからないが、ガベージコレクションが必ずしも要素immediatley 。また、ボタンが親ウィンドウ(spHorizo​​ntal、そして最終的にはMainWindowへの参照)への参照を保持し、GlobalVarが生きているので、MainWindowがまったく処分されず、実際に漏れている可能性があります。

メインウィンドウを一切却下しないで、単に複数のMainWindowを同時に実行しようとするなら、あなたがしようとしていることは不可能です。何らかの形で(基本的にテキストボックスに置いたテキスト)ボタンのリストをシリアル化してから、同じテキストの新しいボタンを作成する必要があります。

MainWindowを終了する場合は、ウィンドウを閉じる前にspHorizo​​ntalからspHorizo​​ntal.Childrenを使用してボタンのリストを削除してください。削除する

あなたのプログラムには、改善の機会がたくさんあります。具体的には、メインウィンドウ(this.IsVisible = false)を隠してから、必要に応じて再度表示するのはなぜですか?または、なぜあなたはあなたのGlobalVarシングルトンにspHorizo​​ntalを保存しないのですか?

また、ボタンに適用するスタイルのbtnTestRegistration_Clickメソッドの部分に設定されているすべてのプロパティを持つほうがずっと良いでしょう。私はアンチコードビハインドファンではありませんが、これは明らかにXAMLを使用すべき場所です。それは私のコードだった場合

ヘックは、私はちょうどその項目のリストとのObservableCollection(各項目は、ボタンを表す)、コレクションにバインド<のItemsControl >を持っていた、とのStackPanelするItemsPanelTemplateを設定します。

<ItemsControl ItemsSource="..."> 
    <!-- Items Source above should point to the list of logical items representing the buttons. --> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <!-- this is the spHorizontal that you have --> 
     <StackPanel Orientation="Vertical" /> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <!-- this is a template for the button: --> 
     <Button ... /> 
    </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 
関連する問題