如何将控件绑定到WPF列表视图列

时间:2011-10-07 08:45:32

标签: wpf listview binding

我是WPF的新手,请原谅我,如果我错过了一些明显的东西

我有以下列表视图控件(为简洁起见,删除了非相关详细信息)

<ListView>
  <ListView.View>
    <GridView>
      <GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}"/>
      <GridViewColumn Header="Details" DisplayMemberBinding="{Binding Details}"/>
    </GridView>
  </ListView.View>
</ListView>

我在

后面的代码中将项添加到此列表视图中
public void Add(LogEntry entry)
{
  ListViewItem item = new ListViewItem();
  item.Content = entry;
  listView.Items.Add(item);
}

其中LogEntry具有“Type”和“Details”的公共字符串属性

到目前为止,这么好,一切都很可爱但是...... 我希望我的details属性本身是一个元素(包含各种类型内容的TextBox或DockPanel) 如何将此元素绑定到列表列?

使用上面的代码,将“Details”更改为元素我只是在列表框中获取类名(例如System.Windows.Control.TextBox),因为默认情况下,单元格显示属性的ToString()值。 我用Google搜索过使用DataTemplate的示例,但我找不到将元素绑定到面板内容的示例。 控件不能在xaml中定义,因为它的结构和内容直到运行时才知道

绑定是一种方式(我只需要显示列表,而不是更新底层数据结构)

为了使我的问题更清楚,我想绑定以下列表项

class LogEntry
{
  public string Type {get;}
  public DockPanel Details {get;} // This dock panel was created by code and contains
                                  // various elements not predictable at compile time
}

3 个答案:

答案 0 :(得分:0)

对不起,我无法给你一个确切的答案,因为我现在没有VS我现在在这里,但有几点指示。

首先,而不是使用您的方法添加Listview项目,您想要使用您的数据创建ObservableCollection。然后,您可以将listview的itemssource绑定到observableCollection。

接下来,你可以为包含你想要的控件的listview创建一个itemtemplate,非常简单就像一个水平方向的堆栈面板和两个文本框。

完成后,因为您已将listview的itemsource设置为ObservableCollection,您只需将文本框绑定到集合中的String属性即可。

请注意,ObservableCollection最好绑定到List,因为ObservableCollection支持NotifyPropertyChanged()。

答案 1 :(得分:0)

我已将您的代码复制到一个新项目中,并在此处创建了相同的列表视图。这个工作并正确显示数据

XAML:

 <ListView x:Name="MyList" ItemsSource="{Binding MyListDetails}">
    <ListView.View>
      <GridView>
         <GridViewColumn Header="Type" DisplayMemberBinding="{Binding Firstname}"/>
         <GridViewColumn Header="Details" DisplayMemberBinding="{Binding Lastname}"/>
      </GridView>
 </ListView.View>

视图模型:

 private List<Contact> _details= new List<Contact>();;
    public List<Contact> MyListDetails
    {
        get
        {
            return _details;
        }
        set
        {
            _details = value;
            this.RaisePropertyChanged("MyListDetails");
        }
    }

 public void AddEntry(LogEntry entry)
 {
   MyListDetails.Add(entry);
 }

答案 2 :(得分:0)

您的模型LogEntry类不应引用UI控件。相反,它应该包含UI所需的数据,而XAML应该定义使用该数据的DataTemplate。例如,

public class LogEntry
{
  public string Type {get;}
  public ObservableCollection<IDetail> Details {get;}
}

<DataGridTemplateColumn Header="Details">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <DockPanel>
                <ItemsControl ItemsSource="{Binding Details}" />
            </DockPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

您提到LogEntry中的DockPanel创建了在运行时未知的项目。你能举个例子吗?在大多数情况下,您应该在数据中使用某种模式,并且可以使用DataTemplates来定义如何绘制每个Detail部分。

<DataTemplate DataType="{x:Type local:LoginDetail}}">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding CreatedDate}" />
        <TextBlock Text="{Binding UserName}" />
        <TextBlock Text="{Binding MachineLoggedIn}" />
    </StackPanel>
</DataTemplate>

<DataTemplate DataType="{x:Type local:LogoutDetail}}">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding CreatedDate}" />
        <TextBlock Text="{Binding UserName}" />
        <TextBlock Text="{Binding LoggedInTime}" />
    </StackPanel>
</DataTemplate>

如果您真的需要在模型中存储控件,那么您可以在ContentControl中使用DataGridTemplateColumn并将其设置为Content等于详细信息

<ContentControl Content="{Binding Details}" />