我是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
}
答案 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}" />