Как получить доступ к данным из ViewModel в теге ItemsSource - PullRequest
0 голосов
/ 25 июня 2019

Я делаю TabControl, который может динамически меняться с помощью тега ItemsSource.Я хочу знать способ доступа к данным ViewModel в теге ItemsSource.

Я искал через Интернет.но я не смог найти ответ.

КОД

public class ViewModel
{
      // this will be used in ItemsSource
      private ObservableCollection<ActiveButton> _allExecuteButtonInfos = new ObservableCollection<ActiveButton>();

      public ObservableCollection<ActiveButton> AllExecuteButtonInfos
      {
        get { return _allExecuteButtonInfos; }
        set {
            _allExecuteButtonInfos = value;
            OnPropertyChanged();
        }
      }

      // I want to get this data in ItemsSource
      private List<string> _boardNameList = new List<string>();

      public string BoardNameList
      {
          get { return _boardNameList; }
          set {
              _boardNameList = value;
              OnPropertyChanged();
          }
      }
}

XAML

<Grid>
   <TabControl Background="#FF292929" ItemsSource="{Binding AllExecuteButtonInfos}">                     
          <TabControl.ContentTemplate>
              <DataTemplate>
                  <ScrollViewer Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
                      <Grid VerticalAlignment="Stretch" Margin="0,0,0,0" >
                          <ComboBox Width="334" Margin="0,0,0,0" Grid.Column="1" Grid.Row="1" Height="22" VerticalAlignment="Top" 
                                   <!-- I want to get data from ViewModel not in ItemsSource(AllExecuteButtonInfos) -->
                                   <!-- eg) VM:BoardNameList, ViewModel.BoardNameList etc -->
                                    ItemsSource="{Binding BoardNameList, Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}"  
                                    SelectedItem="{Binding SelectedBoard, Mode=TwoWay}"/>
                      </Grid>
                  </ScrollViewer>
               </DataTemplate>
          </TabControl.ContentTemplate>
    </TabControl>
</Grid>

Я надеюсь, что ямогу найти ответ.

Спасибо.

Ответы [ 4 ]

1 голос
/ 25 июня 2019

Вы можете привязать к DataContext, то есть к модели представления родительского элемента TabControl, используя RelativeSource:

    <ComboBox ... 
        ItemsSource="{Binding DataContext.BoardNameList, RelativeSource={RelativeSource AncestorType=TabControl}}" />

Обратите внимание, что бессмысленно устанавливать Mode привязки ItemsSource на TwoWay, поскольку элемент управления никогда не устанавливает свойство. Также бессмысленно устанавливать UpdateSourceTrigger в PropertyChanged в этом случае по той же причине.

0 голосов
/ 25 июня 2019

Один из лучших способов - создать UserControl для каждой модели, а затем поместить шаблоны данных в TabControl.Resources с DataType, указанным для всех типов, которые вы можете поместить в ItemsSource - вы получите полную настройку вида с хорошим разделение файлов XAML.

<Grid>
   <TabControl Background="#FF292929" ItemsSource="{Binding AllExecuteButtonInfos}">                     
          <TabControl.Resources>
              <DataTemplate DataType="{x:Type MyViewModel1}">
                   <MyViewModel1_View ViewModel="{Binding}"/>
              </DataTemplate>
              <DataTemplate DataType="{x:Type MyViewModel2}">
                   <MyViewModel2_View ViewModel="{Binding}"/>
              </DataTemplate>
          </TabControl.Resources>
    </TabControl>
</Grid>

Я ухожу из памяти, так что связывание может быть сделано по-другому, но это основная идея.

То есть, или вы используете какой-то ViewResolver в качестве единственного элемента в TabControl (что-то вроде this )

В принципе, иди еще больше MVVM:)

0 голосов
/ 25 июня 2019

При условии, что DataContext вашего представления правильно установлено на ViewModel и AllExecuteButtonInfos действительно доступно в вашем представлении, вы можете использовать RelativeBinding для доступа к свойствам, которых нет в DataContext из ваша текущая сфера.

<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.BoardNameList}" />

При этом вы покидаете неявное DataContext из DataTemplate, то есть ActiveButton, и получаете доступ к объекту указанного типа через AncestorType. Оттуда вы можете установить Path для DataContext из UserControl, который в вашем случае является объектом класса ViewModel.

Представьте, что вы поднимаетесь по лестнице. От объекта ComboBox до вашего UserControl, откуда вы можете получить доступ ко всем базовым свойствам.

0 голосов
/ 25 июня 2019

Я не уверен, где вы определили контекст данных, но я полагаю, что он находится где-то выше первой разметки Grid.Как-то так?

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

Тогда вам нужно как-то обратиться к текстовому тексту окна.Вы можете сделать это следующим образом

<ComboBox                              
ItemsSource="{Binding DataContext.BoardNameList, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}" />

, если имя вашего представления не «MainWindow», вы должны изменить его на имя представления, где у вас есть этот код.

...