WPF页面之间的绑定/在视图模型之间传输数据

时间:2017-07-26 09:22:53

标签: c# wpf mvvm binding

我需要在页面之间传输数据并对其进行“绑定”。 在第一页上,我将文本框绑定到“用户名”属性。 每个页面都有自己的viewmodel,点击第一页中的按钮后,我就完成了这样的事情

SecondPageViewModel.Username = this.Username;

在第二页中,我将textblock绑定到Username属性,但在页面更改后,第二页显示没有文本。

<TextBlock Text="{Binding Username}" />

我发现和工作的唯一方法是在构造函数的第二页viewmodel中创建一个更新用户名的任务。

Task.Run(async () => 
{
    while(true)
    {
        await Task.Delay(200);
        this.Username = FirstPageViewModel.Username;
    }
});

还有其他办法吗?通过在这里完成任务,它并不总是有效,有时如果我更快地更改页面,它无论如何都不会显示用户名。

每个viewmodel都实现了INotifyPropertyChanged + FodyWeaver。

1 个答案:

答案 0 :(得分:0)

根据我的评论,这是一些使用事件的简单实现。

  • 第一个实现是FirstPageViewModel is parent of SecondPageViewModel。您可以在SecondPageViewModel构造函数中看到事件订阅。
  • 第二个实现是FirstPageViewModel is on the same level of SecondPageViewModel。这在两个ViewModel之间使用Mediator。它基本上消除了FirstPageViewModel
  • SecondPageViewModel的依赖关系
  • 第三个是在FirstPageViewModel上创建您自己的委托,以便SecondPageViewModel订阅。它与PropertyChanged基本相同,但您可以配置准备传递的事件参数。

这是一个演示:

public delegate void UsernameChangedEventHandler(string username);

public class FirstPageViewModel : INotifyPropertyChanged
{
    // 3) Third implementation
    public event UsernameChangedEventHandler UsernameChanged;

    private string _username;
    public string UserName
    {
        get { return _username; }
        set
        {
            _username = value;

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("UserName"));

            if (UsernameChanged != null)
                UsernameChanged(this.UserName);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

public class SecondPageViewModel : INotifyPropertyChanged
{

    private string _username;
    public string UserName
    {
        get { return _username; }
        set
        {
            _username = value;

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("UserName"));
        }
    }

    public SecondPageViewModel()
    {
    }

    public SecondPageViewModel(FirstPageViewModel parent)
    {
        // 1) First implementation
        parent.PropertyChanged += FirstPageViewModel_OnPropertyChanged;

        // 3) Third Implementation
        parent.UsernameChanged += Parent_UsernameChanged;
    }

    private void Parent_UsernameChanged(string username)
    {
        this.UserName = username;
    }

    private void FirstPageViewModel_OnPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        FirstPageViewModel parent = (FirstPageViewModel) sender;
        if(args.PropertyName.Equals("username", StringComparison.InvariantCultureIgnoreCase))
        {
            this.UserName = parent.UserName;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

public class ParentViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private FirstPageViewModel _firstPageViewModel;
    private SecondPageViewModel _secondPageViewModel;

    public ParentViewModel()
    {
        // 2) Second implementation
        _firstPageViewModel = new FirstPageViewModel();
        _secondPageViewModel = new SecondPageViewModel();

        _firstPageViewModel.PropertyChanged += FirstPageViewModel_PropertyChanged;


        // 3) Third Implementation
        _firstPageViewModel.UsernameChanged += FirstPageViewModel_UsernameChanged;
    }

    private void FirstPageViewModel_UsernameChanged(string username)
    {
        _secondPageViewModel.UserName = username;
    }

    private void FirstPageViewModel_PropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        FirstPageViewModel firstPageViewModel = (FirstPageViewModel)sender;
        if (args.PropertyName.Equals("username", StringComparison.InvariantCultureIgnoreCase))
        {
            _secondPageViewModel.UserName = firstPageViewModel.UserName;
        }
    }
}