我正在尝试创建一个示例纯 MVVM 应用程序。我的问题是,如果我将 Model 属性绑定到 UI 上的 ListView 项,它运行良好,但是当我尝试绑定 Model 属性的包装器 [在 ViewModel 中创建] 它不起作用。
在我的示例应用程序中,如果我在 FamilyView.xaml\ListView 控件中使用名称和位置 [模型中公开的属性] 属性,它会显示项目,但如果我使用 MemberName 和 MemberLocation [ViewModel 中公开的属性],它不会更新列表。
我对 MVVM 中层之间关系的理解是 ViewModel 将 View & Model 分开。如果是这样,那么我们应该使用 ViewModel 属性绑定到 View 而不是 Model 属性。请建议如何通过将其绑定到 ViewModel 属性来更新我的列表。
我的代码如下:
FamilyView.xaml
<Window x:Class="MVVM_15thSep13.View.FamilyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MVVM_15thSep13.ViewModel"
Title="FamilyView" Height="283" Width="367">
<Window.DataContext>
<local:FamilyViewModel/>
</Window.DataContext>
<Grid>
<TextBox Text="{Binding Family.Name, FallbackValue=BindingFailed}" Height="23" HorizontalAlignment="Left" Margin="12,16,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding Family.Location, FallbackValue=BindingFailed}" Height="23" HorizontalAlignment="Left" Margin="12,57,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" />
<Button Command="{Binding AddDetailsCommand}" Content="Button" Height="23" HorizontalAlignment="Left" Margin="240,31,0,0" Name="button1" VerticalAlignment="Top" Width="93" />
<ListView ItemsSource="{Binding FamilyCollection}" SelectedItem="{Binding Family}" Height="126" HorizontalAlignment="Left" Margin="14,110,0,0" Name="listView1" VerticalAlignment="Top" Width="319" UseLayoutRounding="True">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="120"/>
<GridViewColumn Header="Location" DisplayMemberBinding="{Binding Location}" Width="120"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
家庭模型.cs
namespace MVVM_15thSep13.Model
{
public class FamilyModel:ObservableObject
{
private string m_Name;
private string m_Location;
public string Name
{
get { return m_Name; }
set
{
m_Name = value;
if (m_Name != value)
OnPropertyChanged("Name");
}
}
public string Location
{
get { return m_Location; }
set
{
m_Location = value;
if (m_Location != value)
OnPropertyChanged("Location");
}
}
public FamilyModel()
{
m_Name = "Default Name";
m_Location = "Default Location";
}
public FamilyModel(string name, string location)
{
m_Name = name;
m_Location = location;
}
}
}
FamilyViewModel.cs
namespace MVVM_15thSep13.ViewModel
{
public class FamilyViewModel:ObservableObject
{
private FamilyModel m_Family;
private ObservableCollection<FamilyModel> m_FamilyCollection;
private ICommand m_AddDetailsCommand;
public FamilyViewModel()
{
m_Family = new FamilyModel();
m_FamilyCollection = new ObservableCollection<FamilyModel>();
}
public FamilyModel Family
{
get { return m_Family; }
set
{
if (m_Family != value)
{
m_Family = value;
OnPropertyChanged("Family");
}
}
}
public ObservableCollection<FamilyModel> FamilyCollection
{
get { return m_FamilyCollection; }
set { m_FamilyCollection = value; }
}
public ICommand AddDetailsCommand
{
get
{
if (m_AddDetailsCommand == null)
m_AddDetailsCommand = new RelayCommand(param => AddFamilyDetails(), null);
return m_AddDetailsCommand;
}
}
public void AddFamilyDetails()
{
FamilyCollection.Add(Family);
Family = new FamilyModel();
}
}
}
其他助手类:
中继命令.cs
namespace MVVM_15thSep13.HelperClasses
{
public class RelayCommand:ICommand
{
private readonly Action<object> m_Execute;
private readonly Predicate<object> m_CanExecute;
public RelayCommand(Action<object> exec) : this(exec, null) { }
public RelayCommand(Action<object> exec, Predicate<object> canExec)
{
if (exec == null)
throw new ArgumentNullException("exec");
m_Execute = exec;
m_CanExecute = canExec;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
if (parameter == null)
return true;
else
return m_CanExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
if (m_CanExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (m_CanExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
m_Execute(parameter);
}
#endregion
}
}
ObservableObject.cs
namespace MVVM_15thSep13.HelperClasses
{
public abstract class ObservableObject:INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
#endregion
}
}