我正在开发一个使用MVVM设计模式的应用程序。但是我很难将viewmodel中的命令绑定到视图。 这是我的代码:
我有一个名为 Part
的模型 public class Part
{
private string _partcode;
private string _description;
public string PartCode
{
get { return _partcode.Trim(); }
set { _partcode = value; }
}
public string Description
{
get { return _description; }
set { _description = value; }
}
}
带有命令的ViewModel,名为 PartViewModel
/// <summary>
/// Returns a ViewModel containing all parts.
/// </summary>
/// <param name="dt">Database to use.</param>
public PartViewModel(DatabaseType dt)
{
GenerateViewModelForAllParts(dt);
}
private async void GenerateViewModelForAllParts(DatabaseType dt)
{
using (NexusWCFServiceClient client = new NexusWCFServiceClient())
foreach (Part item in await client.GetAllPartsAsync(dt))
_items.Add(item);
}
#endregion
#region Members
private ObservableCollection<Part> _items = new ObservableCollection<Part>();
private Part _part;
int count = 0;
#endregion
#region Properties
public ObservableCollection<Part> Items
{
get { return _items; }
set { _items = value; }
}
public Part Part
{
get { return _part; }
set { _part = value; }
}
public string PartCode
{
get { return Part.PartCode; }
set
{
if (Part.PartCode != value) /* Check if value is changed */
{
Part.PartCode = value;
RaisePropertyChanged("PartCode"); /* Raise event */
}
}
}
public string Description
{
get { return Part.Description; }
set
{
if (Part.Description != value)
{
Part.Description = value;
RaisePropertyChanged("Description");
}
}
}
public ICommand UpdateDescription
{
get
{
return new RelayCommand(UpdateDescriptionExecute, CanUpdateDescriptionExecute);
}
}
#endregion
}
还有一些辅助类:
ObservableObject
public class ObservableObject : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Methods
public void RaisePropertyChanged(string propertyname)
{
PropertyChangedEventHandler handler = PropertyChanged; // Create a new instance to prevent thread issues
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyname));
}
}
#endregion
}
RelayCommand
public class RelayCommand : ICommand
{
#region Members
private bool _canExec = true;
readonly Func<bool> _canExecute;
readonly Action _execute;
public event EventHandler CanExecuteChanged;
#endregion
#region Constructors
public RelayCommand(Action execute) : this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
public bool CanExecute(object parameter)
{
bool previousCanExec = _canExec;
_canExec = _canExecute == null ? true : _canExecute();
if (previousCanExec != _canExec)
{
CanExecuteChanged(parameter, null);
}
return _canExec;
}
public void Execute(object parameter)
{
_execute();
CanExecute(null);
}
}
在我的MainWindow中,我通过以下方式设置DataContext:
base.DataContext = new PartViewModel("TPGC070", DatabaseType.TestDB);
返回包含give参数的所有部分。好的,直到现在。
在我的 MainWindow 中,我在列表视图中显示了viewmodel:
<Window x:Class="NexusWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="700" Width="525" x:Name="TestBinding">
<Grid>
<StackPanel x:Name="stck">
<ListView x:Name="lb" ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" x:Name="stck">
<TextBlock Text="{Binding Path=PartCode}"/>
<TextBlock Text="{Binding Path=Description}"/>
<Button Content="Update" DataContext="{Binding ElementName=TestBinding, Path=DataContext}" Command="{Binding UpdateDescription}" CommandParameter="{Binding ElementName=lb, Path=DataContext}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel x:Name="sp" DataContext="{Binding ElementName=lb, Path=SelectedItem}">
<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.UpdateDescription}" Content="Update Description"/>
<TextBlock Text="{Binding Path=Description}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
所以我正在尝试的是两件事。我希望listview中的命令更新集合中所选项的描述。它确实找到了命令,但我在viewmodel中的描述中得到以下错误:
An unhandled exception of type 'System.NullReferenceException' occurred in ...
我还尝试创建一个stackpanel,它保存listview的所选项目,然后尝试更新描述。这里会弹出相同的错误。
它尝试了几种绑定语法,但它们都没有工作。我现在使用的那些确实找到了命令,但我在描述中得到了NullReference错误。 我感觉命令和集合并没有彼此绑定,但我似乎无法找出原因。
我在搜索SO时遇到了同样的错误,但似乎无法找到一个处理我的架构所用逻辑的好解决方案。也许它在根或只是一个简单的绑定问题。这就是为什么我不认为它是重复的。
我错过了一些明显的东西吗?任何帮助将不胜感激。