[英]using ModelView in View in MVVM + WPF
I have a model called Entity
which is created by EF database first :我有一个名为
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; }
}
I want this model Implement INotifyPropertyChanged for notifying when X and Y are changing so I created another model like CEntity
我想要这个模型实现 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));
}
}
This is MainWindow.xaml
这是
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>
I have Entities
in my viewmodel as below:我的视图模型中有
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();
}
}
Based on MVVM
we have to use viewmodel instead of model in view, my problem is this part in view:基于
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>
When I use Model CEntity
here it works fine but I don't know what should I put as part of viewmodel instead of CEntity.当我在这里使用 Model
CEntity
,它工作正常,但我不知道我应该把什么作为 viewmodel 的一部分而不是 CEntity。
CEntity
should not inherit from Entity
as it then hides the X
and Y
properties. CEntity
不应从Entity
继承,因为它会隐藏X
和Y
属性。
You'd better use composition and wrap Entity
:您最好使用组合并包装
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));
}
}
You can then bind directly to the X
and Y
properties as usual:然后你可以像往常一样直接绑定到
X
和Y
属性:
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.