我无法将List绑定到DataGrid。它应该尽可能简单。我是WPF的新手,这是我的个人教育。
我有一个View(编辑),ViewModel(VMText)和一个Data(JustText)类。
我的资料来源:
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
<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
namespace View
{
public partial class Editor : Window
{
private ViewModel.VMText vmText;
#region Constructor
public Editor()
{
InitializeComponent();
vmText = new ViewModel.VMText(this);
DataContext = vmText;
}
#endregion
}
}
我只想在DataGrid的一列中显示在VMText中创建的List
答案 0 :(得分:6)
如果您确实想要使用网格编辑Code
中的项目,则需要重写视图模型以使其成为可能。您无法为网格提供字符串集合。你必须给它一个具有字符串 property 的类的集合。这就是WPF的工作方式。
如果您不想编辑它们,只需将IsReadOnly="True"
放在列上,它们将是只读的。
此外,你所有的绑定看起来都像是在随意猜测一切意味着什么。
所以这是一个如何做我想做想要做的事情的例子。我删除了你的Model.Text
课来简化事情。如果没有它你就足够深了。
ViewModels.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
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel.VMText
{
CodeString = "Hello World!\nHow you doin'?"
};
}
MainWindow.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>
答案 1 :(得分:4)
我想你只想在DataGrid中的视图模型的Code source collection属性中显示字符串。
然后,您应该将DataGrid的 ItemsSource 属性绑定到视图模型的Code source属性,然后将DataGridTextColumn绑定到Code列表本身的字符串。您只需稍微修改视图的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>
答案 2 :(得分:3)
您应该实现INotifyPropertyChanged以通知绑定该属性已更改。同样对于集合,请查看ObservableCollection
而不是List
。
答案 3 :(得分:1)
将VMText.Code绑定到DataGrid ItemSource。当您在后面的代码中执行时,您不需要在View中Inicialize DataGrid DataContract。
<强>视图模型强>
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;
}
}
查看强>
<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>