通过 MVVM 数据绑定设置模型的 FK(从组合框)



这是我的第一个WPF MVVM EF项目,虽然经历非常艰难,我怀疑我是否会回到这些项目,但我打算完成它。我有一个可以编辑Hardware模型属性的视图。它适用于"简单"属性,如字符串、int、DateTime等。但由于某些原因,我无法使它适用于该模型仅有的几个FK属性
这是视图模型代码:

<UserControl x:Class="WPFapp.Views.HardwareManipulationWindowView">
<UserControl.Resources>
<DataTemplate DataType="{x:Type localVM:HardwareManipulationViewModel}">
<local:HardwareManipulationWindowView />
</DataTemplate>
</UserControl.Resources>
<ComboBox SelectedValue="{Binding Hardware.CurrentlyBeingUsedByProgram.GUID, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding ProgramsList}" SelectedValuePath="GUID">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</UserControl>
internal class HardwareManipulationViewModel : NotificationObject
{
public HardwareManipulationViewModel(Hardware hardware, ObservableCollection<Program> programsList)
{
Hardware = hardware;
ProgramsList = programsList;
}
public ObservableCollection<Program> ProgramsList { get; set; }
public Hardware Hardware { get; }
internal void WriteChangesInto(Hardware selectedItem)
{
selectedItem.Type = Hardware.Type;
selectedItem.Label = Hardware.Label;
selectedItem.Description = Hardware.Description;
selectedItem.Remarks = Hardware.Remarks;
selectedItem.CurrentLocation = Hardware.CurrentLocation;
selectedItem.CurrentStatus = Hardware.CurrentStatus;
//all of the above work just fine, but these 2 FKs below don't work at all
selectedItem.CurrentlyBeingCarriedByPerson = Hardware.CurrentlyBeingCarriedByPerson; 
selectedItem.CurrentlyBeingUsedByProgram = Hardware.CurrentlyBeingUsedByProgram;
}
}
public class Hardware : NotificationObject
{
protected Hardware()
{
GUID = Guid.NewGuid();
}
Guid _guid;
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid GUID { get { return _guid; } private set { _guid = value; OnPropertyChanged(); } }
string _label;
public string Label { get { return _label; } set { _label = value; OnPropertyChanged(); } }
string _description;
public string Description { get { return _description; } set { _description = value; OnPropertyChanged(); } }
string _remarks;
public string Remarks { get { return _remarks; } set { _remarks = value; OnPropertyChanged(); } }
Program _currentlyBeingUsedByProgram;
public Program CurrentlyBeingUsedByProgram { get { return _currentlyBeingUsedByProgram; } set { _currentlyBeingUsedByProgram = value; OnPropertyChanged(); } }
}

我显然省略了很多噪音代码。对于任何想知道NotificationObject是基本的INotifyPropertyChanged实现的人来说。现在,以上所有内容都在这个单一的方法中处理:

private void InvokeEditHardwareDialog()
{
HardwareManipulationViewModel viewModel = new HardwareManipulationViewModel(SelectedItem.Clone(), new ObservableCollection<Program>(_dbContext.EagerLoad<Program>()));
var window = WindowService.CreateWindowHostingViewModel(viewModel, true);
window.ShowDialog();
if (viewModel.DialogResult.GetValueOrDefault())
{
viewModel.WriteChangesInto(SelectedItem);
_dbContext.Update(SelectedItem);
}
}

现在,问题是:当调试器进入WriteChangesInto方法时,我在其中插入的注释行上方的所有道具都会使用视图更改其新值,但对于最后2个(外键)属性,尽管组合框值加载正确,但不会发生任何事情。Hardware.CurrentlyBeingUsedByProgram包含它开始时的任何值。我在这里做错了什么?据我所知,这应该还可以。

问题最有可能发生在EF和WPF通信之间。我最终使用了一个变通方法,其中包括使用一个额外的属性来存储FK值:

private Program _hardwareProgram;
public Program HardwareProgram { get { return _hardwareProgram; } set { _hardwareProgram = value; OnPropertyChanged(); } }

和XAML:

<ComboBox SelectedValue="{Binding HardwareProgram}"
ItemsSource="{Binding ProgramsList}"  IsSynchronizedWithCurrentItem="True">

然后在你的ctor中,你只需读取值_hardwareProgram = hardware.CurrentlyBeingUsedByProgram;,就可以开始了。

最新更新