绑定到同一解决方案中另一个项目的属性



我是WPF的新手,现在我偶然发现了一些在互联网上找不到答案的事情。我有以下问题:

在同一个解决方案中,我有两个项目。一种是表示生产流程的应用程序,称为MaintenancePlanner。另一个是名为MaintenancePlannerGUI的GUI。

我想要实现的是:按下按钮后,我的生产流程模拟开始(在MaintenancePlanner中进行(。然后,在MaintenancePlannerGUI中,我有一个进度条。进度条的值应根据MaintenancePlanner模拟中对象的属性值进行更改。

因此,我需要以某种方式将其绑定。然而,我不明白该怎么做。我使用MVVM结构。所以我的结构如下:

  • 维护计划器
    • 组装Fab.cs
    • AssemblyLine.cs
    • ShellModel.cs(类似Program.cs,但专门用于MaintenancePlannerGUI(
  • 维护计划GUI
    • 视图
      • ShellViewModel.cs
    • ViewModels
      • ShellView.xaml

例如,AssemblyLine包含属性Speed。请注意,AssemblyLine的多个实例以List<AssemblyLine> AssemblyLines的形式附加到AssemblyFab。

在ShellView.xaml中,我有一个进度条:

<ProgressBar Width="10" Height="45" Margin="0,5,10,0" Orientation="Vertical" Minimum="0" Maximum="50" Value="{Binding ???}"/>

在ShellViewModel.cs中,我通过从MaintenancePlanner创建ShellModel.cs的实例来创建MaintenancePlaner模拟AssemblyFabSim的实例,其中创建了整个AssemblyFab及其组成部分,如下所示:

AssemblyFabSim = new ShellModel();

现在,我尝试了一些非常粗糙的东西,比如:

Value="{Binding AssemblyFabSim.AssemblyFab.AssemblyLines[0].Speed}

但这显然没有奏效。我想到的另一个想法是使用NotifyPropertyChanged方法。

因此,在这种情况下,我可以在ShellViewModel.cs中创建一个名为test的属性,并将其绑定到我的progressbar。然后,如果ShellModel.cs中的属性发生了更改,我可以通过收到通知来更新测试。但是,我还需要从ShellModel.chs中监控AssemblyFab和AssemblyLine中的更改,以便将从AssemblyLine到AssemblyFab到ShellModel到ShellViewModel的更改传播到视图。我对这种方法有点困惑。

private void ShellModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Speed")
{
test = AssemblyFabSim.AssemblyFab.AssemblyLines[0].MouldCleanInterval;
}
}

我想知道这是否真的是一条路,如果是的话,该如何做到这一点?或者还有其他更简单的方法吗?提前感谢!

编辑1

我的ShellViewModel.cs现在包含以下内容,因为ShellViewModel继承了像ShellViewModel : INotifyPropertyChanged这样的INotifyPropertyChanged类

public ShellModel AssemblyFabSim { get; set; }
AssemblyFabSim.PropertyChanged += ShellModel_PropertyChanged;
private void ShellModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "TestSpeed")
{
test = AssemblyFabSim.AssemblyFab.AssemblyLines[0].Speed;
}
}
private double _test;
public double test
{
get { return _test; }
set
{
_test = value;
NotifyOfPropertyChange();
}
}

现在,我将我的进度条值绑定为Value="{Binding test}。然后ShellModel.cs也将继承INotifyPropertyChanged,我添加了:

public void UpdateSpeed()
{
try
{
TestSpeed = AssemblyFab.AssemblyLines[0].Speed;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
NotifyOfPropertyChange(nameof(TestSpeed));
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyOfPropertyChange([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

并且UpdateSpeed((方法是从Assemblyline中调用的。

新问题:processbar的值会更新,但只有在模拟完成后我才能看到结果。也就是说,GUI只是冻结,直到模拟停止,然后显示"速度"的最后一个值。

如果您的shellViewModel具有类似的属性

public ShellModel AssemblyFabSim {get;}

您应该能够绑定到它,如果路径中的所有其他属性都是正确的,它们也应该可以工作。但据我所知,绑定不支持索引器,所以我认为AssemblyLines[0]不起作用。

Wpf并不关心在哪些项目中定义了类,只关心它有一个要绑定的对象,以及属性的名称是否正确。通常,一切都应该实现INotifyPropertyChanged才能正常工作。

但请注意,深度嵌套路径可能不是一个好主意,您应该尝试将UI和业务逻辑分离,因此您应该尽量避免绑定到为其设计的viewModel类以外的任何东西。

值得注意的是,如果你有一个进度条,你应该绑定到一个Progress<T>对象,该对象被传递给需要报告进度的方法。您应该避免在执行工作的对象上使用progress属性,毕竟,如果从多个线程同时调用该方法,会发生什么?

您需要确保在后台线程上调用UpdateSpeed(),因为UI线程不能同时更新进度条和执行代码。

最新更新