3

現在、1 つのメイン ウィンドウと、このウィンドウの子である多くの UserControls を持つ WPF プロジェクトがあります。このウィンドウの子の多くはタブです。メイン ウィンドウを、メイン ウィンドウとほぼ同じ機能を実装するユーザー コントロールに置き換えることに成功しました。

Window を UserControl に置き換えると、1 つの問題が発生しました。現在、アプリケーションは、以下に示す方法を使用して、親ウィンドウに基づいて表示するプログラミング タブを決定しWindow.FindNameます。Application.Current.MainWindowしたがって、メイン ユーザー コントロールの適切な説明に置き換える必要があります。明確にするために、以下のエラーのある C# メソッドと、タブの wpf インスタンス化を参照してください。

Window.FindName() メソッドに関する注意- UserControl に置き換えた後に機能しない理由は、ここで説明されているように、FindName メソッドがビジュアル ツリーを上方向に検索するためです。

のように、x:Name に基づいてユーザー コントロールを見つける方法を知っている人はいますApplication.Current.MainWindowか? また、名前が変更された場合に x:Name 文字列を探すよりも、UserControl を見つけるためのより良い方法はありますか?

現在 MainWindow を見つける方法 - MainUserControl を見つける必要があります。

(C#)
private static void SetCurrentProgram(int num)
    {
        Window window = Application.Current.MainWindow;
        ProgrammingTab programmingTab1 = window.FindName("ProgrammingTab1") as ProgrammingTab;
        ProgrammingTab programmingTab2 = window.FindName("ProgrammingTab2") as ProgrammingTab;

        programmingTab1.Visibility = num == 1 ? Visibility.Visible : Visibility.Collapsed;
        programmingTab2.Visibility = num == 2 ? Visibility.Visible : Visibility.Collapsed;

    }

プログラミング タブのインスタンス化。

(xaml)
<Grid>
 <ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab1" Program="1" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" />
 <ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab2" Program="2" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" />
</Grid>
4

3 に答える 3

3

あなたのアプリは非常に WinForms に似たスタイルで開発されているようです。そのスタイルに固執し、単純に質問に答えるには、次のように、FindName() で UserControl を検索し、再び ProgrammingTab を検索します。

var userControl = (MyUserControl)Application.Current.MainWindow.FindName("userControlName");
var programmingTab1 = (ProgrammingTab)userControl.FindName("ProgrammingTab1");
var programmingTab2 = (ProgrammingTab)userControl.FindName("ProgrammingTab2");
...

ただし、データ バインディングなどの WPF の高度な機能の使用を検討することをお勧めします。静的プロパティによって参照されるシングルトン オブジェクトに DependencyProperty "CurrentProgram" を設定し、コンバーターを使用して Visiblity をそれにデータバインドするだけです。

<ProgrammingTab Visibilty="{Binding CurrentProgram,
   Source={x:Static MyState.Instance},
   Converter={x:Static VisibleIfEqualConverter},
   ConverterParameter=1}" ...>
  ...

この変更により、SetCurrentProgram は単純になります。

public void SetCurrentProgram(int num)
{
   MyState.Instance.CurrentProgram = num;
}

この手法の優れた点は、MyState.Instance.CurrentProgram の値が変更されるたびに、アプリケーション内の任意の ProgrammingTab が自動的に表示または非表示になり、FindName() などでそれらを見つける必要がないことです。

于 2009-11-18T20:27:31.133 に答える
0

この記事はあなたを助けるかもしれません:http://blog.lexique-du-net.com/index.php ?post / 2010/09/14 / UserControl / Control-how-to-get-a-reference-to-an-テンプレートの要素

于 2010-09-15T09:10:10.213 に答える
0

私はこの問題の回避策を見つけました: DependencyObject の子を再帰的に見つけた別の StackOverflow ユーザーのアルゴリズムに基づいて新しいアルゴリズムを作成しました。ここで私の解決策を見つけてください。私の他の投稿で FindChild() メソッドを宣言すると、次のようにし public static class UIHelper {}て問題を解決できます。

  ProgrammingTab programmingTab1 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab1");
  ProgrammingTab programmingTab2 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab2");

これは、RayBurns が提案したようなバインディングに対して、宣言型 XAML の代わりに手続き型コードを引き続き使用します。それが機能する場合、彼のソリューションはツリー全体をトラバースするのではなく、コンバーターに基づいてタブの可視性を変更するだけなので、はるかに効率的です。そのソリューションを今すぐテストして、結果がどうなるか見てみましょう。

The reason why FindName() doesn't work properly is described in the post here.

于 2009-11-19T15:27:07.810 に答える