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

tquggr8v  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(149)

我是WPF的新手,现在我偶然发现了一些在互联网上找不到答案的东西。我有以下问题:
在同一个解决方案中,我有两个项目,一个是代表生产过程的应用程序,称为MaintenancePlanner,另一个是GUI,称为MaintenancePlannerGUI。
我想实现的目标如下:按下按钮后,生产过程的模拟开始(在MaintenancePlanner中进行)。然后,在MaintenancePlannerGUI中,我有一个进度条。进度条的值应根据MaintenancePlanner模拟中对象的属性值进行更改。
因此,我需要以某种方式绑定它。但是,我不知道如何做到这一点。我使用MVVM结构。因此,我的结构看起来如下:

  • 维护计划员
  • AssemblyFab.cs
  • AssemblyLine.cs
  • ShellModel.cs(类似于Program.cs,但仅专门用于维护计划器GUI)
  • 维护计划器GUI
  • 查看次数
  • ShellViewModel.cs
  • 检视模型
  • 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模拟AssemblyFabSim的示例,方法是从MaintenancePlanner创建ShellModel.cs的示例,在MaintenancePlanner中创建了整个AssemblyFab及其组件,如下所示:

AssemblyFabSim = new ShellModel();

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

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

但这显然不起作用。我想到的另一个想法是使用NotifyPropertyChanged方法。
因此,在这种情况下,我可以在ShellViewModel.cs中创建一个名为test的属性,并将其绑定到我的进度条。然后,如果ShellModel.cs中的属性发生更改,我可以通过获取通知来更新测试。但是,我还需要从ShellModel.cs中监视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继承了INotifyPropertyChanged类,如下所示ShellViewModel : 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()**方法。
新问题:进程栏的值被更新,但只有在模拟完成后我才能看到结果。也就是说,GUI只是冻结,直到模拟停止,然后它显示速度的最后一个值。

iaqfqrcu

iaqfqrcu1#

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

public ShellModel AssemblyFabSim {get;}

您应该能够绑定到它,并且如果路径中的所有其他属性都正确,它们也应该可以工作。但据我所知,绑定不支持索引器,所以我认为AssemblyLines[0]将无法工作。
Wpf并不关心类在什么项目中定义,只关心它有一个要绑定的对象,并且属性的命名正确。通常一切都还应该实现INotifyPropertyChanged才能很好地工作。
但是请注意,深度嵌套的路径可能不是一个好主意,您应该尝试将UI和业务逻辑分开,因此您应该尝试避免绑定到除为它设计的viewModel类之外的任何东西。
值得注意的是,如果你有一个进度条,你应该绑定到一个Progress<T>对象,该对象被传递给需要报告进度的方法。你应该避免在执行工作的对象上使用progress-property,毕竟,如果从多个线程并发调用该方法会发生什么?

6g8kf2rb

6g8kf2rb2#

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

相关问题