[英]How to bind list of object to DataGrid in WPF
這是我的代碼背后:
public partial class MainWindow : INotifyPropertyChanged
{
private List<Word> _words;
public List<Word> Words
{
get => _words;
set
{
_words = value;
OnPropertyChanged("Words");
}
}
public MainWindow()
{
InitializeComponent();
MeaningGroup group1 = new MeaningGroup()
{
Synonyms = new List<string> {"synonym1", "synonym2", "synonym3"},
Acronyms = new List<string> {"acronym1", "acronym2"}
};
MeaningGroup group2 = new MeaningGroup()
{
Synonyms = new List<string> { "synonym1"},
Acronyms = new List<string> { "acronym1", "acronym2", "acronym3" }
};
MeaningGroup group3 = new MeaningGroup()
{
Synonyms = new List<string> { "synonym1", "synonym2" },
Acronyms = new List<string> { }
};
MeaningGroup group4 = new MeaningGroup()
{
Synonyms = new List<string> { "synonym1" },
Acronyms = new List<string> { "acronym1", "acronym2", "acronym3","acronym4" }
};
Word word1 = new Word() {Name = "word1",MeaningGroups = new List<MeaningGroup>() {group1, group2}};
Word word2 = new Word() { Name = "word2", MeaningGroups = new List<MeaningGroup>() { group3, group4 } };
Word word3 = new Word() { Name = "word3", MeaningGroups = new List<MeaningGroup>() { group1, group2,group4 } };
Word word4 = new Word() { Name = "word4", MeaningGroups = new List<MeaningGroup>() { group3 } };
Words = new List<Word> {word1, word2, word3, word4};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Word
{
public String Name { get; set; }
public List<MeaningGroup> MeaningGroups { get; set; }
}
public class MeaningGroup
{
public List<string> Synonyms { get; set; }
public List<string> Acronyms { get; set; }
}
這是MainWindow.xaml代碼:
<Window x:Class="WpfApp4.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:WpfApp4"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid ItemsSource="{Binding Words}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Synonym and acronyms">
<!-- How binding? -->
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
我不太理解您的意思,但是如果您想將屬性綁定到列,則可以執行以下操作:
<DataGrid ItemsSource="{Binding Words}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
現在,每個元素的“名稱”將添加到此列。 但是,如果要向一列添加多個屬性,則必須添加DataGridTemplateColumn
:
<DataGrid ItemsSource="{Binding Words}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTemplateColumn Header="Synonyms and Acronyms">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
//There will be all logic. For example
//<TextBlock Text="{Binding Synonyms}"/>
//<TextBlock Text="{Binding Acronyms}"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
但是抱歉,我不知道如果該列傳遞字符串集合(如您的示例)會發生什么。 如果我誤解了你,我很抱歉
更新后的代碼仍然存在綁定錯誤,您需要將此錯誤添加到構造函數的底部:
this.DataContext = this;
您發布的代碼的主要問題在於,您試圖將Synonym和Acronym數組合並到一個列表中,這實際上是在將數據傳遞到視圖層之前應該做的事情。 我將使用轉換器在事后完成此任務,但請記住,這是您稍后可能需要修復的問題。
無論如何,您想要實現的目標都是相對簡單的。 使用DataGridTemplateColumn聲明自定義列類型,並將其內容設置為ItemsControl
(其默認面板為垂直StackPanel)。 堆棧面板的每個元素都是一個MeaningGroup
,因此只需使用另一個ItemsControl呈現標簽,然后將其ItemsPanelTemplate
設置為水平布局即可(我使用了WrapPanel)。 將所有內容放在一起,您會得到:
<Window.Resources>
<behaviors:ListUnionConverter x:Key="ListUnionConverter" />
<DataTemplate x:Key="TagTemplate">
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Margin="5" Padding="5">
<TextBlock Text="{Binding}" />
</Border>
</DataTemplate>
<DataTemplate x:Key="TagListTemplate">
<ItemsControl ItemTemplate="{StaticResource TagTemplate}">
<ItemsControl.ItemsSource>
<MultiBinding Converter="{StaticResource ListUnionConverter}">
<Binding Path="Synonyms" />
<Binding Path="Acronyms" />
</MultiBinding>
</ItemsControl.ItemsSource>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
<DataTemplate x:Key="CellTemplate">
<ItemsControl ItemsSource="{Binding MeaningGroups}" ItemTemplate="{StaticResource TagListTemplate}" />
</DataTemplate>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding Words}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTemplateColumn Header="Synonym and acronyms" IsReadOnly="True" CellTemplate="{StaticResource CellTemplate}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
您還將需要用於將同義詞和首字母縮寫詞合並到單個列表中的轉換器的代碼。 同樣,您應該用更可靠的替代品,或者最好修復數據結構以更好地滿足視圖要求:
結果:
public class ListUnionConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return (values[0] as IEnumerable<string>).Concat(values[1] as IEnumerable<string>).ToArray();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
更新:我剛剛注意到顏色要求不同。 如果絕對必須,也可以使用轉換器來執行此操作,但這是一個非常麻煩的解決方案。 正確的方法是使用中間視圖模型,並將同義詞和首字母縮寫詞合並到一個列表中。
下面的答案解決了這個問題,但我會建議另一種方法。 如上所述,首先需要在代碼隱藏中添加DataContext = this
。 然后只需按如下所示更改xaml標記:
<Grid>
<DataGrid ItemsSource="{Binding Words}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTemplateColumn Header="Synonym and acronyms">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<ItemsControl ItemsSource="{Binding MeaningGroups}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding Synonyms}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Black" CornerRadius="5" Margin="5 5 0 0">
<TextBlock Margin="3" Text="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding Acronyms}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Black" CornerRadius="5" Background="Red" Margin="5 5 0 0">
<TextBlock Margin="3" Text="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.