我正在尝试使用MVVM创建一个使用WPF的UI,但我遇到了一些麻烦。我想要一个包含两列的DataGrid。第一列是标签,第二列中有一个ComboBox。标签列始终显示,但ComboBox中没有显示任何内容。我不认为我正确绑定它,但我不确定如何修复它。
我创建了一个具有我想要在DataGrid中显示的属性的类。标签将是Parameter属性,我有一个名为Revisions for ComboBox的列表属性。
class RevisionMapModel
{
private string _parameter;
public string Parameter
{
get { return _parameter; }
}
private List<string> _revisions;
public List<string> Revisions
{
get { return _revisions; }
}
private string _selection;
public string Selection
{
get { return _selection; }
set { _selection = value; }
}
public RevisionMapModel(string parameter, List<string> revisions)
{
// set the parameter name and the list of revisions
_parameter = parameter;
_revisions = revisions;
_selection = "";
// add a default revision
_revisions.Add("None");
// attempt to find which revision matches with this parameter
FullRevisionMatch(_parameter, _revisions);
// if a full match isn't found, then try again
if (_selection == "None")
{
PartialRevisionMatch(_parameter, _revisions);
}
}
}
以下是用作DataContext的ViewModel类。 DataGrid绑定到RevisionMapModels属性,该属性是前一个类的列表。
class RevisionMapViewModel
{
private string _label;
public string Label
{
get { return _label; }
}
private List<RevisionMapModel> _revisionMapModels;
public List<RevisionMapModel> RevisionMapModels
{
get { return _revisionMapModels; }
}
public RevisionMapViewModel(List<Definition> parameters, List<Revision> revisions, string label)
{
// instantiate the list
_revisionMapModels = new List<RevisionMapModel>();
_label = label;
// convert the parameters and revisions to strings
List<string> revisionDescriptions = revisions.Select(r => r.Description).ToList();
List<string> parameterNames = parameters.Select(p => p.Name).ToList();
// create classes for each parameter
List<string> reservedRevisions = new List<string>();
for (int i=0; i< parameterNames.Count; i++)
{
RevisionMapModel model = new RevisionMapModel(parameterNames[i], revisionDescriptions);
// check to ensure this parameter is not mapped to a revision that is already selected
if (reservedRevisions.Contains(model.Selection))
{
// change the selection to none if it's already used
model.Selection = "None";
}
else
{
reservedRevisions.Add(model.Selection);
}
// add it to the list
_revisionMapModels.Add(model);
}
}
}
这是我的XAML。我猜它无法绑定到Revisions属性,因为它是一个列表。我已经尝试了很多东西,但似乎没有任何东西可以显示出来。
<Window x:Class="SheetRevisions.RevisionMapView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SheetRevisions"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" MinWidth="500" MinHeight="500" Width="500">
<Grid>
<DataGrid Margin="20,40,20,45" MinWidth="50" MinHeight="47" ItemsSource="{Binding RevisionMapModels}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Parameter Name" Binding="{Binding Parameter}" Width="Auto"/>
<DataGridComboBoxColumn Header="Revision Description" ItemsSource="{Binding Revisions}" Width="*" />
</DataGrid.Columns>
</DataGrid>
<Label Content="{Binding Label}" HorizontalAlignment="Left" Height="25" Margin="20,10,0,0" VerticalAlignment="Top" Width="412"/>
<Button Content="Cancel" HorizontalAlignment="Right" Margin="0,0,20,10" VerticalAlignment="Bottom" Width="75" IsCancel="True"/>
<Button Content="OK" HorizontalAlignment="Right" Margin="0,0,110,10" VerticalAlignment="Bottom" Width="75" IsDefault="True"/>
</Grid>
</Window>
我是WPF的新手,所以感谢任何帮助。
答案 0 :(得分:1)
如前所述,您需要在ViewModel中实现INotifyPropertyChanged。像
这样的东西RevisionMapViewModel : INotifyPropertyChanged
//...your code here
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
然后,我认为RevisionMapModel应该是一个公共类。 此外,如果您在Visual Studio中工作,可以在“输出”窗口中看到有关错误绑定的一些提示。
答案 1 :(得分:0)
除了上面关于实现INotifyPropertyChanged的注释之外,我还需要更改我的XAML以使用DataGridTemplateColumn而不是DataGridComboBoxColumn。它与我从这篇文章中发现的列表不是有效来源有关:
工作XAML:
<Window x:Class="SheetRevisions.RevisionMapView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SheetRevisions"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" MinWidth="500" MinHeight="500" Width="500">
<Grid>
<DataGrid Margin="20,40,20,45" MinWidth="50" MinHeight="47" ItemsSource="{Binding RevisionMapModels}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Parameter Name" Binding="{Binding Parameter}" Width="*" IsReadOnly="True"/>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Revisions}" SelectedItem="{Binding Selection}" Width="Auto"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Label Content="{Binding Label}" HorizontalAlignment="Left" Height="25" Margin="20,10,0,0" VerticalAlignment="Top" Width="412"/>
<Button Content="Cancel" HorizontalAlignment="Right" Margin="0,0,20,10" VerticalAlignment="Bottom" Width="75" IsCancel="True"/>
<Button Content="OK" HorizontalAlignment="Right" Margin="0,0,110,10" VerticalAlignment="Bottom" Width="75" IsDefault="True"/>
</Grid>
</Window>
修订模型:
public class RevisionMapModel : INotifyPropertyChanged
{
#region fields
private Logger _logger = LogUtils.LogFactory.GetCurrentClassLogger();
private string _parameter;
public string Parameter
{
get { return _parameter; }
set { }
}
private List<string> _revisions;
public List<string> Revisions
{
get { return _revisions; }
}
private string _selection;
public string Selection
{
get { return _selection; }
set
{
_selection = value;
OnPropertyRaised("Selection");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public RevisionMapModel(string parameter, List<string> revisions)
{
// set the parameter name and the list of revisions
_parameter = parameter;
_revisions = revisions;
_selection = "";
// add a default revision
_revisions.Add("None");
// attempt to find which revision matches with this parameter
FullRevisionMatch(_parameter, _revisions);
// if a full match isn't found, then try again
if (_selection == "None")
{
PartialRevisionMatch(_parameter, _revisions);
}
}
protected void OnPropertyRaised(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}