Добавление в XAML WPF из ViewModel (MVVM) - PullRequest
0 голосов
/ 26 августа 2018

первая попытка MVVM и WPF (крутая кривая обучения). В моей ViewModel я хочу запустить следующий код, чтобы добавить «layoutDocument», который является макетом AvalonDock, в мой интерфейс Mainform.

Класс ViewModel:

LayoutDocument layoutDocument = new LayoutDocument { Title = "Plan Layout" };

Window mainWindow = Application.Current.Windows.OfType<Window>().Where(x => x.Name == "MainWindow").FirstOrDefault();
if (mainWindow != null)
{
    mainWindow.mainPanel.Children.Add(layoutDocument);
}

Приведенный выше код выдает мне следующую ошибку:

"Окно" не содержит определения для mainPanel и метод расширения для mainPanel ".

Обратите внимание, что в моем XAML ниже "LayoutDocumentPane" содержит имя "mainPanel".

Я попытался добавить приведенный выше код непосредственно в мой класс представления MainForm (за исключением бита оператора Application.Current.Windows.OfType и If) и просто включить: mainPanel.Children.Add (layoutDocument); И это работает нормально (новый макет создается в моей MainForm, когда я нажимаю кнопку).

Однако, поскольку я хочу придерживаться MVVM, это не подходящее решение.

Как я могу добавить "layoutDocument" в MainWindow из ViewModel? Заранее спасибо.

Выдержка из моего XAML выглядит так:

<Window x:Class="LiveExplorer.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:LiveExplorer"
             xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
             xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
             xmlns:s="clr-namespace:System;assembly=mscorlib"
             xmlns:vm="clr-namespace:WpfApp1.ViewModel">

<Grid> etc etc etc here---

                <xcad:LayoutDocumentPaneGroup>
                    <xcad:LayoutDocumentPane x:Name="mainPanel">
                        <xcad:LayoutDocument ContentId="document1" Title="Document 1" >
                            <Button Content="Document 1 Content" HorizontalAlignment="Center" VerticalAlignment="Center" 
                                    Command="{Binding NewPlanCommand, Source={StaticResource viewModel}}" 
                                    />
                        </xcad:LayoutDocument>
                        <xcad:LayoutDocument ContentId="document2" Title="Document 2">
                            <TextBox Text="Document 2 Content" AcceptsReturn="True"/>
                        </xcad:LayoutDocument>
                    </xcad:LayoutDocumentPane>
                </xcad:LayoutDocumentPaneGroup >

EDIT:

Хотя принятый ответ не отвечает на вопрос в терминах MMVM, он исправляет ошибку кодирования.

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Это не относится к MVVM, но для доступа к mainPanel вам необходимо преобразовать Window в MainWindow:

MainWindow mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
{
    mainWindow.mainPanel.Children.Add(layoutDocument);
}

Модель представления не должна иметь доступаокно прямо, хотя.Это нарушает шаблон MVVM.

0 голосов
/ 27 августа 2018

То, что вы пытались реализовать, не соответствует шаблону MVVM.Для начала вам нужно позаботиться о 3 вещах:

  • ViewModels
  • Инициализация ViewModel, привязанного к окну
  • Привязка ViewModel к пользовательскому интерфейсу в XAML

ViewModels:

Создайте модель представления, которая будет привязана к вашему MainWindow, и создайте наблюдаемую коллекцию внутри этого MainWindowViewModel, которая содержит список объектов, которые будут содержать данные, которыеможет использоваться в пользовательском интерфейсе:

public ObservableCollection<LayoutDocumentViewModel> LayoutDocument {get;set;}

Убедитесь, что и MainWindowViewModel, и LayoutDocumentViewModel наследуют от INotifyPropertyChanged ( Реализация уведомления об изменении свойства ) или если вы используете MVVMLight (или аналогичный) изViewModelBase.

LayoutDocumentViewModel - это просто ViewModel, который будет использоваться для хранения информации о вашем документе макета и может быть привязан к пользовательскому интерфейсу.

public LayoutDocumentViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    [NotifyPropertyChangedInvocator]

    protected virtual void OnPropertyChanged([CallerMemberName] 
        string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string _name;

    public string Name
    {
      get { return _name; }
      set
      {
          _name = value;
          // Call OnPropertyChanged whenever the property is updated
          OnPropertyChanged("Name");
      }
    }

}

Я настоятельно рекомендую вам использоватьMVVMLight (или аналогичный) или поместите код INotifyPropertyChange в базовый класс, т.е. ViewModeНапример,

Для простоты в этом примере я инициализирую наблюдаемую коллекцию и создаю несколько объектов макетов документов непосредственно в MainWindowViewModel, но вам нужно изучить это дальше и выяснить, где он находится.Вам подходит для их инициализации и / или создания.

public MainPageViewModel () {DocumentLayouts = new ObservableCollection ();DocumentLayouts.Add (new DocumentLayout {Name = "Layout1"});DocumentLayouts.Add (new DocumentLayout {Name = "Layout2"});}

Выше описано, как создать MainWindowViewModel и документы макета.

Инициализация MainViewModel (и привязка к MainWindow.xaml).Обратите внимание, что это быстрый и грязный способ начать работу, и вам действительно следует изучить контейнеры IoC.

<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>

Наконец, свяжите свой ViewModel & UI

XAML:

<Grid>
    <ItemsControl ItemsSource="{Binding LayoutDocuments}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Content="{Binding Name}"/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

Примечание. Просто замените метку элементом управления LayoutDocument и привяжите его к соответствующим свойствам элемента, которые вы объявили в LayoutDocumentViewModel.

Надеюсь, это поможет вам начать.

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