Как передать информацию из одного WPF UserControl в другой WPF UserControl? - PullRequest
4 голосов
/ 08 мая 2009

У меня есть приложение 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, который передает ему информацию, полученную из модели, поэтому пользователь может переходить от страницы к странице, и каждая страница может выполнять изолированные функции, такие как редактирование всех клиентов, сохранение в базе данных и т. д.

Проблема:

Однако теперь на одной из этих страниц я хочу иметь ListBox со списком клиентов, и у каждого клиента есть кнопка «Изменить», и когда эта кнопка редактирования нажата, я хочу заполнить DockPanel. с помощью EditSingleCustomer UserControl и передайте его клиенту, который необходимо отредактировать.

Я могу загрузить пользовательский контроль EditCustomer, но как мне передать его клиенту для редактирования и настроить его DataContext для редактирования этого клиента ?

  • Я не могу передать его в конструкторе, так как все пользовательские элементы управления уже созданы и существуют в словаре в MainWindow.xaml.cs.
  • поэтому я создал метод PrepareUserControl для каждого UserControl и передал ему Customer, который может отображать его с текстовым полем из кода с x: Name = "...", но это не главное, мне нужно DataBind ItemsControl к ObservableCollection, чтобы воспользоваться преимуществами функциональности привязки данных WPF.
  • , поэтому я попытался привязать ListBox ItemSource в представлении к его коду:

<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 () в этом представлении. Так что я думаю, что я поступаю об этом неправильно, должна быть какая-то более простая парадигма, чтобы просто передавать команды от одного UserControl к другому UserControl в WPF (и до того, как кто-то скажет «использовать командование WPF» Я уже использую командование на моем UserControl, которое позволяет пользователю редактировать всех клиентов, что работает нормально, но я должен обрабатывать это в моем коде позади моего представления (а не в моей viewmodel), так как мне нужен контекст родительского окна для иметь возможность загрузить другой пользовательский элемент управления после его сохранения:

<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, если кто-то может указать мне правильное направление отсюда, это было бы замечательно, или если вы думаете, что эта «загрузка UserControls в шаблон DockPanel чужда» в WPF, и его следует избегать и заменять другим способом структурирования приложений », что также будет полезной новостью. Вы можете загрузить текущее состояние моего приложения здесь , чтобы получить представление о его структуре. Спасибо.

Ответы [ 3 ]

3 голосов
/ 08 мая 2009

Здесь вы используете паттерн «Посредник». Есть несколько сообщений в блоге на эту тему (для экземпляр ), и есть реализации шаблона в некоторых платформах WPF (таких как EventAggregator в Prism ).

3 голосов
/ 12 мая 2009

Я только что закончил LOB-приложение, использующее WPF, где постоянно возникал такой тип проблем / шаблонов, поэтому вот как я бы решил вашу проблему:

1) В шаблоне данных, где вы создаете каждый элемент в ListBox, вместе с его кнопкой редактирования, привяжите свойство тега Button к объекту Customer, лежащему в основе этого элемента списка.

2) Создайте обработчик события Click для кнопки и установите событие Click кнопки для запуска обработчика.

3) В обработчике событий установите свойство Content элемента UserControl.

4) Установите шаблон данных в области пользовательского элемента управления (возможно, в ресурсах его непосредственного контейнера), который описывает редактор для этого отдельного клиента.

Другой подход, который будет работать, - объявить свойство зависимостей Customer в вашем классе EditCustomer, а затем установить это свойство (возможно, с помощью триггера XAML) при нажатии кнопки.

Надеюсь, это не слишком расплывчато. Если не более того, знайте, что проблема, с которой вы сталкиваетесь, очень хорошо разрешима в WPF.

1 голос
/ 08 мая 2009

У меня нет времени, чтобы по-настоящему разобраться в этом (это интересный вопрос, и я надеюсь, что вы получите хороший ответ - я вижу, что в будущем столкнусь с подобной ситуацией).

Рассматривали ли вы получить немного меньше WPF-ов и вернуться к запуску события в вашем исходном UserControl с EventArgs, содержащим клиента, а затем в обработчике событий, запустив соответствующую команду на целевом элементе управления?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...