5

WPFアプリケーションがあります。

左側にはボタンでいっぱいのスタックパネルがあります。

右側には空のドックパネルがあります。

ユーザーがボタンをクリックすると、対応するUserControl(ビュー)がドックパネルにロードされます。

private void btnGeneralClick(object sender, System.Windows.RoutedEventArgs e)
{
    PanelMainContent.Children.Clear();
    Button button = (Button)e.OriginalSource;
    Type type = this.GetType();
    Assembly assembly = type.Assembly;

    IBaseView userControl = UserControls[button.Tag.ToString()] as IBaseView;
    userControl.SetDataContext();

    PanelMainContent.Children.Add(userControl as UserControl);
}

このパターンは、各UserControlがモデルから取得した情報をフィードするViewModelクラスを持つビューであるため、うまく機能します。したがって、ユーザーはページからページへクリックでき、各ページはすべての顧客の編集などの分離された機能を実行できます。データベースへの保存など。

問題:

ただし、これらのページの1つに、顧客のリストを含むリストボックスが必要であり、各顧客には「編集」ボタンがあり、その編集ボタンをクリックすると、DockPanelにEditSingleCustomerを入力します。 UserControlを使用して、編集する必要のある顧客を渡します。

EditCustomerユーザーコントロールをロードできますが、編集する顧客を渡し、その顧客を編集するためにDataContextを設定するにはどうすればよいですか?

  • すべてのUserControlが既に作成されており、MainWindow.xaml.csのディクショナリに存在するため、コンストラクターに渡すことができません。
  • そのため、各UserControlにPrepareUserControlメソッドを作成し、Customerをそのメソッドに渡し、x:Name = "..."を使用してコードビハインドからテキストボックスで表示できますが、それは重要ではありません。ItemsControlをにDataBindする必要があります。もちろん、WPFのデータバインディング機能を利用するためのObservableCollection。
  • そのため、ビュー内のListBoxItemSourceを次のようにコードビハインドにバインドしようとしました。

<UserControl.Resources>
    <local:ManageSingleCustomer x:Key="CustomersDataProvider"/>
</UserControl.Resources>

<DockPanel>
    <ListBox ItemsSource="{Binding Path=CurrentCustomersBeingEdited, Source={StaticResource CustomersDataProvider}}"
             ItemTemplate="{DynamicResource allCustomersDataTemplate}"
             Style="{DynamicResource allCustomersListBox}">
    </ListBox>
</DockPanel>

そのビューのIntializeComponent()の無限ループが原因でスタックオーバーフローエラーが発生します。したがって、これについては間違った方法で行っていると思います。WPFで1つのUserControlから別のUserControlにコマンドを渡すだけの簡単なパラダイムが必要です(誰かが「WPFコマンドを使用する」と言う前に、私はすでにコマンドを使用していますUserControlで、ユーザーがすべての顧客を編集できるようにします。これは正常に機能しますが、親ウィンドウコンテキストで別のユーザーを読み込むことができるようにする必要があるため、ビューの背後にあるコードで(ビューモデルではなく)処理する必要があります。保存が終了したときの制御:

<Button Style="{StaticResource formButton}" 
        Content="Save" 
        Command="local:Commands.SaveCustomer"
        CommandParameter="{Binding}"/>

private void OnSave(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
    Customer customer = e.Parameter as Customer;
    Customer.Save(customer);

    MainWindow parentShell = Window.GetWindow(this) as MainWindow;
    Button btnCustomers = parentShell.FindName("btnCustomers") as Button;
    btnCustomers.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}

では、WPFで、UserControlをDockPanelにロードし、そのUserControl内に、別のUserControlをロードし、そのUserControlにコントロールをバインドできる特定のオブジェクトを送信するコマンドを含むボタンを設定するにはどうすればよいでしょうか。

この時点では、WPFコマンドについて十分に理解していないと想像できます。誰かがここから正しい方向に私を向けることができれば、それは素晴らしいことです。または、この「DockPanelパターンでのUserControlsの読み込みはWPFとは無関係であり、回避し、アプリケーションを構造化する別の方法に置き換える必要があります」と、これも役立つニュースです。アプリケーションの現在の状態をここからダウンロードして、アプリケーションがどのように構成されているかを知ることができます。ありがとう。

4

3 に答える 3

4

この種の問題/パターンが絶えず発生するWPFを使用したLOBアプリケーションを終了したばかりなので、次の方法で問題を解決できます。

1)リストボックス内の各アイテムを作成するDataTemplateで、その編集ボタンとともに、ボタンのタグプロパティをそのリストボックスアイテムの下にあるCustomerオブジェクトにバインドします。

2)ボタンのClickイベントハンドラーを作成し、ボタンのClickイベントを設定してハンドラーを起動します。

3)イベントハンドラーで、UserControlのContentプロパティを設定します。

4)その単一の顧客のエディターを記述するユーザーコントロールのスコープ内(おそらくその直接のコンテナーのリソース内)にDataTemplateをセットアップします。

動作する別のアプローチは、EditCustomerクラスでCustomer依存関係プロパティを宣言し、ボタンがクリックされたときにそのプロパティを(おそらくXAMLトリガーを介して)設定することです。

これが曖昧すぎないことを願っています。他に何もない場合は、直面している問題がWPFで非常に解決可能であることを知ってください。

于 2009-05-12T18:07:20.847 に答える
3

ここでMediatorパターンを使用します。このトピックに関するいくつかのブログ投稿があり(たとえば)、一部のWPFフレームワーク(PrismのEventAggregatorなど)にパターンの実装があります。

于 2009-05-08T15:59:47.773 に答える
1

私にはこれを実際に掘り下げる時間がありません(これは興味深い質問であり、あなたが良い答えを得ることを願っています-私は将来同様の状況に遭遇するのを見ることができます)。

WPF-yを少し減らして、顧客を含むEventArgsを使用してソースUserControlでイベントを発生させ、次にイベントハンドラーでターゲットコントロールで適切なコマンドを発生させることを検討しましたか?

于 2009-05-08T15:09:15.070 に答える