WPF绑定对象到模板

时间:2017-12-04 14:10:03

标签: c# wpf xaml data-binding

我定义了两个类,如下所示:

public class Task {

    public string TaskName { get; set; }
    public string Description { get; set; }
    public string Priority { get; set; }
    public List<Job> listofjobs = new List<Job>();

}

public class Job
{
    public string ID { get; set; }
    public string Name { get; set; }

}

生成数据后,我在List中有几个Task对象:

public static List<Task> tasklist = new List<Task>();

其中每个任务都有几个工作。此列表将数据绑定到列表框。像这样:

        Task newTask = new Task();
        Job newJob = new Job();
        Job newJob2 = new Job();

        newTask.Description = "Task 1";
        newJob.job_name = "Job 1";
        newJob.job_name = "Job 2";


        newTask.listofjobs.Add(newJob);
        newTask.listofjobs.Add(newJob2);
        tasklist.Add(newTask);
        joblist.ItemsSource = tasklist;

XAML看起来像这样:

<ListBox Name="joblist" HorizontalContentAlignment="Stretch" >
      <ListBox.ItemTemplate>

                    <DataTemplate>
              <Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">

                  <Expander.ContentTemplate>
                      <DataTemplate>
                          <Border>
                             <WrapPanel>
                                  <Label Content="{Binding Path=ID, RelativeSource={RelativeSource AncestorType=local:Job}}"></Label>
                             </WrapPanel>
                          </Border>
                      </DataTemplate>
                  </Expander.ContentTemplate>
              </Expander>

           </DataTemplate>

      </ListBox.ItemTemplate>
</ListBox>

通过数据绑定生成扩展器可以完美地工作。另一方面,生成扩展器的内容现在确实需要工作。

我想通过数据绑定到指定的扩展器内容中的WrapPanel来实现Task对象中的作业。

结果应该是我有几个扩展器(Task对象),内容中有几个wrappanels(Parent任务的Job对象)。

有谁知道我在这里做错了什么/如何实现这个目标?

修改

我试着提供了下水道:

  <Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">
                            <ListView ItemsSource="{Binding Path=listofjobs}" >
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <StackPanel Orientation="Vertical">
                                            <Label Content="{Binding Path=Name}"></Label>

                                        </StackPanel>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
                        </Expander>

还有:

                        <DataTemplate>
                        <Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">
                            <ListView ItemsSource="{Binding Path=listofjobs}" >
                                        <StackPanel Orientation="Vertical">
                                            <Label Content="{Binding Path=Name}"></Label>

                                        </StackPanel>
                            </ListView>
                        </Expander>
                    </DataTemplate>

但两者似乎都不起作用。我在这里缺少什么?

EDIT2:

出现了几个绑定错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'listofjobs' property not found on 'object' ''Task' (HashCode=49998812)'. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Error: 40 : BindingExpression path error: 'Name' property not found on 'object' ''Task' (HashCode=49998812)'. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'ListViewItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'ListViewItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment')

2 个答案:

答案 0 :(得分:2)

由于您成功绑定Description,您的绑定必须为List<Task> tasklist

想象一下你的视觉树:

- ListBox                                               - Binds List<Task>
    - ListBoxItem  (Expander)                           - Binds Task
        - ListBoxItem (ExpanderContent)- ListView       - Binds Task.Jobs (List<Job>)
            - ListView.ItemTemplate                     - Binds Job

因此,您只能访问Task

的内容

您的Expanders ControlTemplate应展示Job s的集合:

<Expander.ContentTemplate>
    <DataTemplate>
         <ListView ItemsSource="{Binding Jobs}" >
             <ListView.ItemTemplate>
                  <DataTemplate>
                      <TextBlock Text="{Binding Name}" />
                  </DataTemplate>
             </ListView.ItemTemplate>
         </ListView>            
    </DataTemplate>
</Expander.ContentTemplate>

你只绑定一个这样的工作:

<Label Content="{Binding Path=Jobs[0].ID" />

你在这里不需要任何RelativeSource

确保您绑定的每个属性都有一个getter / setter {get;设置;}!

public List<Job> ListOfJobs {get; set;} = new List<Job>();

答案 1 :(得分:0)

我认为在您的列表框中完全绑定您的VM会更容易,例如:

<ListBox Name="joblist" HorizontalContentAlignment="Stretch" ItemsSource={Binding Path=tasklist}> ... </ListBox>

扩展器可以保持不变:

 <Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">

对于您的内容定义,请执行以下操作:

<ListView ItemsSource={Binding Path=listofjobs} >
   <StackPanel Orientation="Vertical">
      <Label Content="{Binding Path=ID}"></Label>
   </StackPanel>
 </ListView>

将您的任务列表公开为属性,并将其定义为您的页面/列表框的DataContext,我认为它应该正常工作。