【问题标题】:Setting ViewModel Property from Method in Another Project从另一个项目中的方法设置 ViewModel 属性
【发布时间】:2017-10-27 20:49:12
【问题描述】:

这里是初学者 - 我正在努力解决访问视图模型属性的问题。在我的特殊情况下,我有一个包含两个不同项目的解决方案。一个包含 UI 组件,另一个包含大部分“工作”。

我的 UI 项目中的视图模型包含以下属性:

   private int _createfileprogress { get; set; }

   public int CreateFileProgress
    {
        get { return _createfileprogress ; }
        set
        {
            if (value == _createfileprogress )
                return;

            _createfileprogress = value;
            OnPropertyChanged("CreateFileProgress");
        }
    }

这个int属性的作用是填充一个进度条的进度。我想在我的另一个项目中引用它,其中执行了一个长时间运行的方法:

    public void LongRunningMethod()
    {
        CreateFileProgress= 0;

        // Do some calculations

        CreateFileProgress= 10

        // More calculations and external calls

        CreateFileProgress= 20

        // etc.
    }

但我找不到连接这两者的正确方法。我确定这样做是错误的 - 将不胜感激任何指导。谢谢!

【问题讨论】:

标签: c# wpf mvvm


【解决方案1】:

我希望我能理解你的问题。 您的 ViewModel 和 View 在同一个项目中,您想监控另一个项目中的模型的进度吗?

我认为您正在搜索事件/观察者模式

在 MVVM 中,模型并不关心 ViewModel 和 View。 MVVM 中的 Prober Way 是模型引发 Viewmodel 可以订阅的事件。

.Net 中的一般事件示例

你可以像这样创建一个 EventArgs 类

    public class ProgressEventArgs :EventArgs
    {
        public int CurrentProgress { get; }

        public ProgressEventArgs(int progress)
        {
            CurrentProgress = progress;
        }
    }

并在您的模型 (LongRunningMethod) 类中创建事件

    public event EventHandler<ProgressEventArgs> ProgressChanged;
    protected void OnProgressChanged(int progress)
    {
        ProgressChanged?.Invoke(this, new ProgressEventArgs(progress));
    }

所以你的方法可以引发事件

    public void LongRunningMethod()
    {
        OnProgressChanged(0);

        // Do some calculations

        OnProgressChanged(10);

    // More calculations and external calls

        OnProgressChanged(20);

    // etc.
    }

ViewModel 订阅的内容

    public class ProgressViewModel
    {
        public ProgressViewModel()
        {
            var model = new Model();
            model.ProgressChanged += (sender, e) => {
                //invoke ui thread
                Application.Current.Dispatcher.Invoke(
                  new Action(() => 
                   {
                     CreateFileProgress = e.CurrentProgress; 
                   }));

            };
        }
    }

【讨论】:

  • 我是在模型还是视图模型中创建 EventArgs 类?
  • 我会在模型中创建
【解决方案2】:

似乎最能帮助您的方法是将您的 UI 元素(窗口、页面或 ProgressBar 本身)的 DataContext 设置为您的 ViewModel,这将允许您的 UI 绑定到 ViewModel 属性。由于您的 ViewModel 似乎实现了 INotifyPropertyChanged 接口,因此您的 OnPropertyChanged() 方法应该在您使用 DataBinding 时自动使 UI 保持最新。

您首先需要引用包含“工作”的类库项目。这将允许您的“UI 项目”从以下位置访问资源(即 ViewModel) “工作项目”。在解决方案资源管理器中右键单击“UI 项目”下的 References,选择 Add Reference...,找到 Projects 选项卡在左侧,然后选中您的“工作项目”复选框。应用它,您的“UI 项目”现在可以访问您的“工作项目”。

完成后,您可以使用以下任一方法来生成我认为您正在寻找的结果:

将 Window 的 DataContext 设置为您的 ViewModel

(最适合当您的窗口中的许多元素将使用您的 ViewModel 中的资源时)

<Window
    //Some attributes
    //Some more attributes
    xmlns:vm="clr-namespace:MyWorkProject.ViewModels;assembly=MyWorkProject">        
    <Window.DataContext>
        <vm:MyViewModel/>
    </Window.DataContext>
    <Grid>
        <ProgressBar Value="{Binding CreateFileProgress}/>
    </Grid>
</Window>

使用 StaticResources 仅设置 ProgressBar 的 DataContext

(如果你不需要整个 Window 的 DataContext 作为 ViewModel 最好)

<Window
    //Some attributes
    //Some more attributes
    xmlns:vm="clr-namespace:MyWorkProject.ViewModels;assembly=MyWorkProject">        
    <Window.Resources>
        <vm:MyViewModel/>
    </Window.Resources>
    <Grid>
        <ProgressBar Value="{Binding Source={StaticResource MyViewModel}, Path=CreateFileProgress}/>
    </Grid>
</Window>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多