如何从 ItemsSource 标签中的 ViewModel 访问数据

How to access data from ViewModel in ItemsSource tag

我正在制作可以使用 ItemsSource 标记动态更改的 TabControl。 我想知道如何访问 ItemsSource 标签中的 ViewModel 数据。

我通过互联网搜索。但我找不到答案。

代码

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>

希望我能找到答案。

谢谢。

我不确定您在哪里定义了数据上下文,但我想它在第一个 'Grid' 标记上方的某处。是这样的吗?

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

然后您必须以某种方式引用 window 的 Datacontext。你可以这样做

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

如果您的视图名称不是 'MainWindow',您必须将其更改为您拥有该代码的视图名称。

最好的方法之一是为每个模型创建一个 UserControl,然后将数据模板放入 TabControl.Resources 中,并为可以放入 ItemsSource 中的所有类型指定 DataType - 你通过很好地分离 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 :)

只要您的视图 DataContext 正确设置为您的 ViewModel 并且 AllExecuteButtonInfos 在您的视图中确实可用,您可以使用 RelativeBinding 访问不在您当前范围的 DataContext 中的属性。

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

这样,您将离开 DataTemplate 的隐式 DataContext,即 ActiveButton,并通过 AncestorType 访问指定类型的对象。从那里您可以将 Path 设置为 UserControlDataContext,在您的情况下,它是 class ViewModel 的对象。

想象你正在爬梯子。从 ComboBox 对象到您的 UserControl,您可以从那里访问所有基础属性。

您可以使用 RelativeSource:

绑定到父 TabControlDataContext,即视图模型
    <ComboBox ... 
        ItemsSource="{Binding DataContext.BoardNameList, RelativeSource={RelativeSource AncestorType=TabControl}}" />

请注意,将 ItemsSource 绑定的 Mode 设置为 TwoWay 是没有意义的,因为控件从不设置 属性。出于同样的原因,在这种情况下将 UpdateSourceTrigger 设置为 PropertyChanged 也是没有意义的。