C#,WPF,将 List<string> 绑定到 DataGrid
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41381502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#, WPF, bind List<string> to DataGrid
提问by dipa2016
I have trouble to bind a List to a DataGrid. It should be as simple as possible. I'm new to WPF and this is for my personal education.
我无法将 List 绑定到 DataGrid。它应该尽可能简单。我是 WPF 的新手,这是为了我的个人教育。
I have a View(Editor),ViewModel(VMText) and a Data(JustText) class.
我有一个 View(Editor)、ViewModel(VMText) 和一个 Data(JustText) 类。
My source so far:
到目前为止我的来源:
JustText.cs
文字版
namespace Model
{
public class Text
{
private string _code;
public string Code
{
get { return _code; }
set { _code = value; }
}
public Text()
{
_code = "Hello World!\nHow you doin'?";
}
}
}
VMText.cs
虚拟机文本文件
namespace ViewModel
{
public class VMText
{
private Model.Text _code;
public List<string> Code
{
get { return new List<string>(_code.Code.Split('\n')); }
set { _code.Code = System.String.Join("\n", value.ToArray()); }
}
private View.Editor editor;
public VMText(View.Editor editor)
{
_code = new Model.Text();
this.editor = editor;
}
}
}
Editor.xaml
编辑器.xaml
<Window x:Class="View.Editor"
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:View"
mc:Ignorable="d"
Title="Editor" Height="240.024" Width="269.895">
<Grid Background="#FF292929" Margin="0,0,-6.8,0.4">
<DataGrid x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="200pt"
Height="100pt"
DataContext="{Binding vmText}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Code, UpdateSourceTrigger=PropertyChanged}" Foreground="Black" Width="60" Header="Test" IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Editor.xaml.cs
编辑器.xaml.cs
namespace View
{
public partial class Editor : Window
{
private ViewModel.VMText vmText;
#region Constructor
public Editor()
{
InitializeComponent();
vmText = new ViewModel.VMText(this);
DataContext = vmText;
}
#endregion
}
}
I just want to show List which is created in VMText in one column in the DataGrid
我只想在 DataGrid 的一列中显示在 VMText 中创建的 List
回答by 15ee8f99-57ff-4f92-890c-b56153
If you really want to use the grid to edit the items in Code, you need to rewrite your viewmodel to make that possible. You can't give the grid a collection of strings. You have to give it a collection of some class that has a string property. That's the way WPF works.
如果您真的想使用网格来编辑 中的项目Code,则需要重写您的视图模型以使其成为可能。你不能给网格一个字符串集合。你必须给它一个具有字符串属性的类的集合。这就是 WPF 的工作方式。
If you don't want to edit them, just put IsReadOnly="True"on the column and they'll be read-only.
如果您不想编辑它们,只需将它们放在IsReadOnly="True"列上,它们就会是只读的。
Also, all your bindings look like you're guessing haphazardly at what everything means.
此外,您所有的绑定看起来都像是在胡乱猜测一切的含义。
So here's an example of how to do what I thinkyou're trying to do. I eliminated your Model.Textclass to simplify things. You're in deep enough without it.
因此,这里有一个示例,说明如何做我认为您正在尝试做的事情。我取消了你的Model.Text课程以简化事情。没有它,你已经足够深了。
ViewModels.cs
视图模型.cs
namespace ViewModel
{
#region ViewModelBase
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] String propName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
#endregion INotifyPropertyChanged
}
#endregion ViewModelBase
// This is the class we'll put in the grid.
public class CodeItem : ViewModelBase
{
private String _value = default(String);
public String Value
{
get { return _value; }
set
{
if (value != _value)
{
_value = value;
OnPropertyChanged();
}
}
}
}
public class VMText : ViewModelBase
{
public String CodeString
{
get {
return String.Join("\n", Codes.Select(ci => ci.Value));
}
set
{
var q = (value ?? "")
.Split(new[] { '\n' })
.Select(s => new CodeItem { Value = s });
Codes = new ObservableCollection<CodeItem>(q);
}
}
#region Codes Property
private ObservableCollection<CodeItem> _codes = default(ObservableCollection<CodeItem>);
public ObservableCollection<CodeItem> Codes
{
get { return _codes; }
set
{
if (value != _codes)
{
_codes = value;
OnPropertyChanged();
}
}
}
#endregion Codes Property
}
}
MainWindow.xaml.cs
主窗口.xaml.cs
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel.VMText
{
CodeString = "Hello World!\nHow you doin'?"
};
}
MainWindow.xaml
主窗口.xaml
<!--
Heights and widths in XAML aren't expressed in "pt" units.
That's CSS. Give XAML a floating point value with no unit specified.
Added AutoGenerateColumns="False" so you don't get a clone of the column
with "Value" for a header.
-->
<DataGrid
x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
ItemsSource="{Binding Codes}"
AutoGenerateColumns="False"
Width="200"
Height="100"
>
<DataGrid.Columns>
<!--
Removed UpdateSourceTrigger=PropertyChanged because it has no effect.
Removed IsReadOnly="false" because it's the default already.
-->
<DataGridTextColumn
Binding="{Binding Value}"
Width="120"
Header="Test"
/>
</DataGrid.Columns>
</DataGrid>
回答by mm8
I guess you simply want to display the strings in the Code source collection property of the view model in the DataGrid.
我猜您只是想在 DataGrid 中的视图模型的代码源集合属性中显示字符串。
You should then bind the ItemsSourceproperty of the DataGrid to the Code source property of the view model and then bind the DataGridTextColumn to the strings in the Code list itself. You just have to modify the XAML markup of your view a bit to be able to see the strings. Try this:
然后,您应该将DataGrid的ItemsSource属性绑定到视图模型的 Code 源属性,然后将 DataGridTextColumn 绑定到代码列表本身中的字符串。您只需稍微修改视图的 XAML 标记即可看到字符串。尝试这个:
<DataGrid x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="200pt"
Height="100pt"
ItemsSource="{Binding Code}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding}"
Foreground="Black" Width="60" Header="Test" IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>


回答by Johnny
You should implement INotifyPropertyChangedto notify binding that property changed. Also for the collections look at ObservableCollectioninstead of List.
您应该实现INotifyPropertyChanged以通知绑定该属性已更改。对于集合,请查看ObservableCollection而不是List.
回答by Dawid Wekwejt
Bind VMText.Code to DataGrid ItemSource. You don't need to Inicialize DataGrid DataContract in View when you do it in code behind.
将 VMText.Code 绑定到 DataGrid ItemSource。在后面的代码中执行时,不需要在 View 中初始化 DataGrid DataContract。
ViewModel
视图模型
namespace ViewModel
{
public class VMText : INotifyPropertyChanged
{
public VMText(View.Editor editor)
{
_code = new Model.Text();
this.editor = editor;
}
public List<string> Code
{
get
{
return new List<string>(_code.Code.Split('\n'));
}
set
{
_code.Code = System.String.Join("\n", value.ToArray());
NotifyPropertyChanged("Code");
}
}
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private Model.Text _code;
private View.Editor editor;
}
}
View
看法
<Window x:Class="View.Editor"
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:View"
mc:Ignorable="d"
Title="Editor" Height="240.024" Width="269.895">
<Grid Background="#FF292929" Margin="0,0,-6.8,0.4">
<DataGrid x:Name="dataGrid"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top"
Width="200pt"
Height="100pt"
ItemsSource="{Binding Code}>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Code"
Foreground="Black" Width="60"
Header="Test"
IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>
</Grid>

