【问题标题】:How to assign ItemsSource property如何分配 ItemsSource 属性
【发布时间】:2017-03-21 14:30:12
【问题描述】:

好的,对不起我之前的混乱。

情况是这样的: 我有两个自定义对象定义如下: 主对象:

public class MainObject
{
    private string mainObjectName;
    public string MainObjectName { get { return mainObjectName; } }

    private List<SubObject> subObjectData;
    public List<SubObject> SubObjectData { get { return subObjectData; } }

    public MainObject(string name, List<SubObject> objectData)
    {
        mainObjectName = name;
        subObjectData = objectData;
    }
}

子对象:

public class SubObject
{
    private string subObjectName;
    public string SubObjectName { get { return subObjectName; } }

    private List<int> integerData;
    public List<int> IntegerData { get { return integerData; } }

    public SubObject(string name, List<int> data)
    {
        subObjectName = name;
        integerData = data;
    }
}

我还有一个视图模型,为简单起见,它使用这两个对象定义了一些数据,如下所示:VM

public List<Model.MainObject> VMList = new List<Model.MainObject>()
    {
        new Model.MainObject("MainItem1", new List<Model.SubObject>()
        {
            new Model.SubObject("SubItem1", new List<int>() { 1,6,3}),
            new Model.SubObject("SubItem2", new List<int>() { 5,2,9})
        }),
        new Model.MainObject("MainItem2", new List<Model.SubObject>()
        {
            new Model.SubObject("SubItem1", new List<int>() { 0,3,1}),
            new Model.SubObject("SubItem2", new List<int>() { 7,5,2})
        })
    };

现在我有以下用户界面

<Grid>
    <ItemsControl Name="MainObjectIC">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding MainObjectName}"/>
                    <ItemsControl Name="SubObjectIC">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding SubObjectName}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

我在后面的代码中分配 MainObjectIC 的 ItemsSource,如下所示:

ViewModel.VM dc = new ViewModel.VM();

    public MainWindow()
    {
        InitializeComponent();
        DataContext = dc;
        MainObjectIC.ItemsSource = dc.VMList;
    }

我还想将 ItemsSource 分配给 SubObjectIC,但要做到这一点,我必须获取 ItemsControl 对象。这就是我想要实现的目标。

据我了解,从后面的代码中分配 ItemsSource 属性可能非常糟糕且无用。

【问题讨论】:

  • 我认为“子”集合绑定的相对来源应该可以工作。我这样做只是为了找到祖先类型的窗口,但我认为它会允许更多类型。
  • 标记中到处都有{Binding ...} 绑定。为什么不能从 xaml 绑定 RelicItemsSource 的 ItemsSource?
  • 是的,但我不知道该怎么做,因为 RelicItemsSource 应该依赖于绑定到 ComponentsItemsSource 的对象。另外我认为我需要将 DataContext 绑定到“this”而不是我的客户对象。
  • 似乎方法不对,但您可以为此使用 Binding ElementName
  • 如果您在解决问题时需要帮助,请修正您的问题,以便在其中包含一个很好的 minimal reproducible example,清楚地显示您尝试过的内容,并准确解释您无法弄清楚的内容。跨度>

标签: c# wpf xaml itemssource


【解决方案1】:

感谢您改进代码示例。它还不是很完整,但已经足够接近可以提供答案了。

在您的示例中,缺少的主要内容是简单地添加必要的 {Binding} 表达式。特别是:

<ItemsControl Name="SubObjectIC" Grid.Column="1"
              ItemsSource="{Binding SubObjectData}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding SubObjectName}"/>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

该项目的上下文已经是MainObject 类型的对象(这就是您的TextBlock 绑定有效的原因)。所以剩下要做的就是将ItemsSource 属性绑定到MainObject.SubObjectData 属性。

(我必须添加 Grid.Column 分配,您上面的示例中似乎缺少该分配。)

上述更改完全足以让您的示例按您的意愿工作。但是,您也可以通过对顶级控件使用相同的基本方法来改进代码。为此,您的 VM.VMList 字段需要更改为属性(WPF 仅绑定到属性,而不是字段):

class VM
{
    public List<MainObject> VMList {  get { return _vmList; } }

    private readonly List<MainObject> _vmList = new List<MainObject>()
    {
        new MainObject("MainItem1", new List<SubObject>()
        {
            new SubObject("SubItem1", new List<int>() { 1,6,3}),
            new SubObject("SubItem2", new List<int>() { 5,2,9})
        }),
        new MainObject("MainItem2", new List<SubObject>()
        {
            new SubObject("SubItem1", new List<int>() { 0,3,1}),
            new SubObject("SubItem2", new List<int>() { 7,5,2})
        })
    };
}

然后您可以删除构造函数中的显式赋值:

public MainWindow()
{
    InitializeComponent();
    DataContext = dc;
}

通过这些更改,您的 XAML 不再需要提供任何控件名称,并且您可以直接绑定到相关属性:

<Window x:Class="TestSO42929995WpfNestedData.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestSO42929995WpfNestedData"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <ItemsControl ItemsSource="{Binding VMList}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition/>
              <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding MainObjectName}"/>
            <ItemsControl Grid.Column="1"
                          ItemsSource="{Binding SubObjectData}">
              <ItemsControl.ItemTemplate>
                <DataTemplate>
                  <TextBlock Text="{Binding SubObjectName}"/>
                </DataTemplate>
              </ItemsControl.ItemTemplate>
            </ItemsControl>
          </Grid>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
  </Grid>
</Window>

上面可能不明显的一个关键点是每个控件都有一个DataContext。当您使用 {Binding} 语法时,默认情况下,属性路径是相对于该上下文的。在顶级控件中,上下文是您在构造函数中设置的内容。但是在单个列表项模板中,上下文是该列表项的单个数据对象,在您的情况下是 MainObject 对象。因此,在这种情况下,您只需绑定到SubObjectData 属性,就像绑定到MainObjectName 一样。它的工作原理完全相同,并且出于相同的原因。

【讨论】:

  • 哦,上帝请杀了我,我真是个白痴。非常感谢您浪费时间
  • @George:没必要对自己那么苛刻。如果您真的是个白痴,您将不会接受有关您的原始帖子以及如何改进它的反馈(相信我,Stack Overflow 上有很多这样的人)。虽然我怀疑 Stack Overflow 上存在 类似 问题,但我搜索但没有找到任何与您的问题完全一样的问题。即使有,这个现在也有一个很好的、简单的代码示例来说明问题和答案,这似乎不是浪费时间。 :)
  • 感谢您的支持和良好的态度:)
猜你喜欢
  • 2018-08-27
  • 2012-01-08
  • 2011-11-10
  • 2020-06-13
  • 1970-01-01
  • 2022-11-27
  • 2011-05-22
  • 2011-03-05
  • 1970-01-01
相关资源
最近更新 更多