让我们从INotifyPropertyChanged接口开始,并介绍如何实现它。一般来说,我试图创建一个抽象类,Model和ViewModel都使用这个抽象类,它包含了我的所有模型和viewmodels中常见的一切。以下是这些抽象类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace WpfStackOverflow.Models
{
public abstract class modelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public void SetPropertyChanged([CallerMemberName] string property = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
#endregion
}
namespace WpfStackOverflow.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public void SetPropertyChanged([CallerMemberName] string property = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
以下是我创建的视图模型:
namespace WpfStackOverflow.ViewModels
{
class BasicMVVMViewModel:ViewModelBase
{
private ObservableCollectionEx<LocationKPI> _locations;
public BasicMVVMViewModel()
{
CreateTestData();
}
private DateTime _selectedDate;
public DateTime SelectedDate
{
get { return _selectedDate; }
set
{
_selectedDate = value;
SetPropertyChanged();
SetSelectedLocationKPI( _selectedDate.Month);
}
}
private LocationKPI _selectedLocationKPI;
public LocationKPI SelectedLocationKPI
{
get { return _selectedLocationKPI; }
set
{
_selectedLocationKPI = value;
SetPropertyChanged();
}
}
private void SetSelectedLocationKPI(long sMonth)
{
SelectedLocationKPI = _locations.Where(p => p.SMonth.Equals(sMonth)).FirstOrDefault();
}
private void CreateTestData()
{
_locations = new ObservableCollectionEx<LocationKPI>();
for(int i=0; i < 12;i++)
{
_locations.Add(new LocationKPI() { SMonth = i, Efficiency = i*17 });
}
}
}
}
<UserControl x:Class="WpfStackOverflow.Controls.BasicMVVM"
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:WpfStackOverflow.Controls"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition Height="35"/>
<RowDefinition Height="35"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DatePicker HorizontalAlignment="Left" Margin="30,5,0,0" Grid.Row="1" VerticalAlignment="Top" Width="150" SelectedDate="{Binding SelectedDate}"/>
<TextBlock x:Name="textBlock" HorizontalAlignment="Stretch" Grid.Row="2" TextWrapping="Wrap"
Text="{Binding SelectedLocationKPI.Efficiency,Mode=TwoWay}" VerticalAlignment="Stretch" Margin="5"/>
</Grid>
</UserControl>
在Viewmodel中,我调用了一个创建测试数据的方法。在您的情况下,您可以从linq查询中获取数据。(你弄明白了:)
您必须调整一些引用和命名以适应您的环境。我在这里发布的内容经过了测试,效果良好。我希望它能帮助您更好地理解MVVM。哦,是的,还有一件事,你在这里看到的XAML来自用户控件,而不是XAML窗口。在代码隐藏中,您必须实例化ViewModel并将其设置为DataContext:
namespace WpfStackOverflow.Controls
{
public partial class BasicMVVM : UserControl
{
public BasicMVVM()
{
InitializeComponent();
DataContext = new BasicMVVMViewModel();
}
}
}