DataContext для привязки UserControl с ViewModel в DataTemplate - PullRequest
2 голосов
/ 21 сентября 2011

Я пытаюсь добиться:

  • Привязать ListView к ObservableCollection ItemRecords.
  • Иметь TabControl, который содержит подробное представление для всех ItemRecords вListView, которые были выбраны для редактирования.
  • Каждый TabItem содержит UserControl ("ItemInfo"), который использует ItemInfoViewModel в качестве своей виртуальной машины (и, не случайно, DataContext).
  • ItemInfo UserControl должен бытьзаполнены данными из соответствующей ItemRecord.

Для этого я пытаюсь передать ItemRecord (выбранный в ListView) в ItemInfoViewModel.

Наконец, вопрос : как вы думаете, что будет лучшим способом сделать это, не нарушая паттерн MVVM?

Не слишком элегантный способ, который я вижу (и на самом деле он не совсем следуетпринципы MVVM), для которого в UserControl определен элемент DependencyProperty ItemRecord, предоставьте его значение через привязку и в конструкторе (в UserControКод l-code) передает ItemRecord в виртуальную машину (которую мы получаем путем приведения DataContext).

Другая проблема заключается в том, как на самом деле передать ItemRecord через привязку.После того, как я установил виртуальную машину как DataContext UserControl, я не могу просто использовать {Binding}, чтобы указать текущий элемент в исходной коллекции TabControl.На данный момент я привязываюсь к SelectedItem элемента TabControl, используя ElementName - но это звучит не слишком надежно: - (

<localControls:TabControl.ContentTemplate>
    <DataTemplate>
        <ScrollViewer>
            <localControls:ItemInfo ItemRecord="{Binding ElementName=Tabs, Path=SelectedItem}"/>
        </ScrollViewer>
    </DataTemplate>
</localControls:TabControl.ContentTemplate>

Любой хороший совет будет принят по достоинству!

Alex

1 Ответ

1 голос
/ 21 сентября 2011

Я думаю, что ваша проблема в том, что вы не совсем понимаете паттерн MVVM; Вы по-прежнему смотрите на это, когда различные органы управления разговаривают друг с другом . Там, где в MVVM их не должно быть, каждый элемент управления взаимодействует с моделью представления независимо от всех остальных. И модель представления контролирует (и снабжает) логику, которая сообщает элементам управления, как себя вести.

Итак, в идеале вы должны иметь что-то вроде:

public ObservableCollection<ItemRecord> ListViewRecords 
{
   get { ... }
   set { ... }
}

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set { ... }
}

ListViewRecords будет привязан к свойству ItemsSource вашего ListView (фактические свойства могут отличаться в зависимости от используемых вами элементов управления, на данный момент я привык к Telerik Suite, так что это где моя голова). И SelectedListViewRecords будет привязан к свойству SelectedItems ListView. Тогда для вашего TabControl вы должны иметь:

public ObservableCollection<MyTabItem> Tabs
{
   get { ... }
   set { ... }
}

public MyTabItem SelectedTab
{
   get { ... }
   set { ... }
}

Опять же, вы должны связать свойство Items с Tabs и SelectedItem с SelectedTab на TabControl. Теперь ваша модель представления содержит всю логику, поэтому в вашем SelectedListViewRecords вы можете сделать что-то вроде этого:

public IEnumerable<ItemRecord> SelectedListViewRecords {
{
   get { ... }
   set 
   {
       _selectedRecords = value;
       NotifyPropertyChanged("SelectedListViewRecords");

       Tabs.Clear(); // Clear the existing tabs
       // Create a new tab for each newly selected record
       foreach(ItemRecord record in value)
          Tabs.Add(new MyTabItem(record)); 
   }
}

Таким образом, идея заключается в том, что элементы управления не делают ничего, кроме отправки и получения изменений свойств, они ничего не знают о базовых данных, логике и т. Д. Они просто показывают, что их связанные свойства говорят им показать.

...