我有一个名为Entity
的模型,它首先由EF数据库创建:
public partial class Entity
{
public Entity()
{
this.Properties = new HashSet<Property>();
}
public long Id { get; set; }
public string Name { get; set; }
public int X { get; set; }
public int Y { get; set; }
public virtual ICollection<Property> Properties { get; set; }
}
我想要这个模型实现 INotifyPropertyChanged 以通知 X 和 Y 何时更改,所以我创建了另一个模型,例如CEntity
public class CEntity : Entity, INotifyPropertyChanged
{
private int _x;
private int _y;
public CEntity()
{
}
public CEntity(long id, string name, int x, int y)
{
Id = id;
Name = name;
_x = x;
_y = y;
}
public int X
{
get => _x;
set
{
_x = value;
OnPropertyChanged();
}
}
public int Y
{
get => _y;
set
{
_y = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
这是MainWindow.xaml
<Window x:Class="DomainModelEditor.UI.MainWindow"
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"
mc:Ignorable="d"
xmlns:local="clr-namespace:Example.UI"
xmlns:example="clr-namespace:Example"
xmlns:models="clr-namespace:Example.Models"
xmlns:vm="clr-namespace:Example.UI.ViewModels"
Title="Modeler" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="0,0,0,1" BorderBrush="Black">
<StackPanel Orientation="Horizontal" Height="26">
<Label Content="Domain Model Editor" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button Width="80" Content="Add Entity" Margin="0,3,0,3" Click="AddEntity_Click"/>
</StackPanel>
</Border>
<ItemsControl x:Name="EditorCanvas" Grid.Row="1" ItemsSource="{Binding Path=Entities}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=(models:CEntity.X)}" />
<Setter Property="Canvas.Top" Value="{Binding Path=(models:CEntity.Y)}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type models:CEntity}">
<Thumb HorizontalAlignment="Right" VerticalAlignment="Top" DragDelta="Thumb_OnDragDelta" MouseDoubleClick="Thumb_MouseDoubleClick">
<Thumb.Template>
<ControlTemplate>
<Grid>
<Rectangle Width="80" Height="50" RadiusX="4" RadiusY="4" Stroke="Black" Fill="LightBlue"/>
<Label Content="{Binding Path=Name}"/>
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
我的视图模型中Entities
如下:
public class MainViewModel
{
private readonly IEntityRepository _entityRepository;
private readonly IUnitOfWork _unitOfWork;
public MainViewModel(IEntityRepository entityRepository, IUnitOfWork unitOfWork)
{
_entityRepository = entityRepository;
_unitOfWork = unitOfWork;
Entity = new CEntity();
Entities = new ObservableCollection<CEntity>();
}
public void Load()
{
var entities = _entityRepository.GetAll().Select(entity => new CEntity()
{
Id = entity.Id,
Name = entity.Name,
X = entity.X,
Y = entity.Y
});
Entities.Clear();
foreach (var entity in entities)
{
Entities.Add(entity);
}
}
public ObservableCollection<CEntity> Entities { get; set; }
public void Add(string name, int x, int y)
{
var entity = new Entity()
{
Name = name,
X = x,
Y = y
};
_entityRepository.Add(entity);
_unitOfWork.Save();
}
}
基于MVVM
我们必须使用视图模型而不是视图中的模型,我的问题是视图中的这部分:
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=(models:CEntity.X)}" />
<Setter Property="Canvas.Top" Value="{Binding Path=(models:CEntity.Y)}" />
</Style>
</ItemsControl.ItemContainerStyle>
当我在这里使用模型CEntity
时,它工作正常,但我不知道我应该将什么作为视图模型的一部分而不是 CEntity。
CEntity
不应该从Entity
继承,因为它会隐藏X
和Y
属性。
你最好使用构图和包装Entity
:
public class CEntity : INotifyPropertyChanged
{
private readonly Entity _entity;
public CEntity(Entity entity)
{
_entity = entity;
}
public int X
{
get => _entity.X;
set
{
_entity.X = value;
OnPropertyChanged();
}
}
public int Y
{
get => _entity.Y;
set
{
_entity.Y = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
然后,您可以像往常一样直接绑定到X
和Y
属性:
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />