C# 如何在WPF中将对象列表绑定到DataGrid

C# 如何在WPF中将对象列表绑定到DataGrid,c#,wpf,data-binding,datagrid,C#,Wpf,Data Binding,Datagrid,这是我的代码隐藏: public partial class MainWindow : INotifyPropertyChanged { private List<Word> _words; public List<Word> Words { get => _words; set { _words = value; OnPropertyChang

这是我的代码隐藏:

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; }
}
公共部分类主窗口:INotifyPropertyChanged
{
私人名单(字);;
公共列表词
{
get=>\u单词;
设置
{
_文字=价值;
不动产变更(“文字”);
}
}
公共主窗口()
{
初始化组件();
MeaningGroup group1=新的MeaningGroup()
{
同义词=新列表{“同义词1”、“同义词2”、“同义词3”},
缩略语=新列表{“缩略语1”,“缩略语2”}
};
MeaningGroup group2=新的MeaningGroup()
{
同义词=新列表{“同义词1”},
缩略语=新列表{“缩略语1”、“缩略语2”、“缩略语3”}
};
MeaningGroup Group 3=新的MeaningGroup()
{
同义词=新列表{“同义词1”,“同义词2”},
缩写词=新列表{}
};
MeaningGroup group4=新的MeaningGroup()
{
同义词=新列表{“同义词1”},
缩略语=新列表{“缩略语1”、“缩略语2”、“缩略语3”、“缩略语4”}
};
word1=newword(){Name=“word1”,意思是groups=newlist(){group1,group2};
word2=newword(){Name=“word2”,意思是groups=newlist(){group3,group4};
word3=newword(){Name=“word3”,意思是groups=newlist(){group1,group2,group4};
word4=newword(){Name=“word4”,意思是groups=newlist(){group3};
单词=新列表{word1,word2,word3,word4};
}
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共类词
{
公共字符串名称{get;set;}
公共列表含义组{get;set;}
}
公共类含义组
{
公共列表同义词{get;set;}
公共列表首字母缩略词{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>

但是很抱歉,我不知道如果该列传递字符串集合会发生什么情况(如您的示例中所示)。如果我误解了您的意思,我很抱歉

您更新的代码仍然存在绑定错误,您需要将其添加到构造函数的底部:

    this.DataContext = this;
您发布的代码的主要问题是,您试图将同义词和首字母缩写词数组合并到一个列表中,这实际上是在将数据传递到视图层之前应该做的事情。我将在事后使用转换器来完成此任务,但请记住,这可能是您以后应该解决的问题

在任何情况下,你想要实现的目标都是相对简单的。使用DataGridTemplateColumn声明自定义列类型,并将其内容设置为
ItemsControl
(其默认面板为垂直堆叠面板)。堆栈面板的每个元素都是一个
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();
    }
}
公共类ListUnionConverter:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,CultureInfo区域性)
{
return(值[0]为IEnumerable).Concat(值[1]为IEnumerable.ToArray();
}
公共对象[]转换回(对象值,类型[]目标类型,对象参数,CultureInfo区域性)
{
抛出新的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>

     <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>