【问题标题】:WPF Parent event handler using MVVM使用 MVVM 的 WPF 父事件处理程序
【发布时间】:2021-04-21 03:02:18
【问题描述】:

似乎我想与here提出的问题相反。我有一个使用 MVVM 模式的 WPF 应用程序。主视图决定了要显示的视图

<!-- Content -->
<ContentControl Grid.Row="1" Content="{Binding CurrentView, Mode=OneWay}" />

CurrentView 是“当前”视图。在同一个主视图模型中,我还有通过绑定到视图模型上的“IsValid”来启用和禁用的按钮

<Button Content="{x:Static r:Resources.Next}" Background="LawnGreen"
                Command="{Binding NextCommand,Mode=OneWay}"
                IsEnabled="{Binding Path=IsValid,Mode=TwoWay}"
                Visibility="{Binding Path=IsNextVisible,Converter={StaticResource BoolToVis}}"/>

这有一个简单的实现,例如:

public bool IsValid
{
    get
    {
        return CurrentView.IsValid;
    }
    set
    {
        RaisePropertyChanged();
    }
}

但是您会注意到“IsValid”标志来自于当前视图。因此,每个视图都确定它是否有效。 In one of these views (UserControls) I have a ComboBox that when something is selected the "IsValid" for that view should go from false to true.这看起来像:

private Client selectedItem;
public Client SelectedItem
{
    get { return selectedItem; }
    set
    {
        selectedItem = value;
        IsValid = true;
        ProvisionService.SelectedClient = selectedItem;
        RaisePropertyChanged();
        RaisePropertyChanged("IsValid");
    }
}

private bool _isValid;
public bool IsValid
{
    get
    {
        return _isValid;
    }
    set
    {
        _isValid = value;
        RaisePropertyChanged();
    }
}

我看到的问题是,父母似乎没有看到在子视图中从 false 变为 true 的事件。如何通知父母孩子的这个属性发生了变化?

这是CurrentView的实现

private IProvisionView _currentView;
public IProvisionView CurrentView
{
    get { return _currentView; }
    set
    {
        _currentView = value;
        RaisePropertyChanged();
        RaisePropertyChanged(nameof(IsValid));
        RaisePropertyChanged(nameof(IsPrevVisible));
        RaisePropertyChanged(nameof(IsNextVisible));
        RaisePropertyChanged(nameof(IsHomeVisible));
    }
}

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    您可以做与 WPF 相同的事情。分配给 PropertyChanged 事件。 如果您的 CurrentView 已设置:

    // old (if assigned)
    _currentView.PropertyChanged -= CurrentView_PropertyChanged;
    // new
    value.PropertyChanged += CurrentView_PropertyChanged;
    

    然后检查它是否是 IsValid 属性

    【讨论】:

    • 恐怕我不明白这个提议的解决方案。子视图模型引发属性更改事件。这个视图模型不知道它是一个孩子,也没有访问父属性“CurrentView”的权限。因为它是“CurrentView”的视图模型。例如,我有带有视图模型 AViewModel 和 BViewModel 的 AView 和 BView。两个视图都有一个 IsValid 属性,该属性绑定到每个视图模型上的一个属性。如问题描述中所示,当前引发了一个事件来更改它。父视图模型上还有一个EventHandler?
    • @KevinBurton:视图模型中的CurrentView属性是如何实现的?
    【解决方案2】:

    每当CurrentView 属性在父视图模型中设置为新值时,您应该将事件处理程序连接到子视图模型的PropertyChanged 事件并通过引发@ 的PropertyChanged 事件来处理它Button绑定的父视图模型的987654324@属性,例如:

    private INotifyPropertyChanged _currentView;
    public INotifyPropertyChanged CurrentView
    {
        get { return _currentView; }
        set
        {
            if (_currentView != null)
                _currentView.PropertyChanged -= OncurrentViewPropertyChanged;
            _currentView = value;
            if (_currentView != null)
                _currentView.PropertyChanged += OncurrentViewPropertyChanged;
        }
    }
    
    private void OncurrentViewPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "IsValid") // = nameof(ChildViewModel.IsValid)
            RaisePropertyChanged("IsValid"); // = nameof(IsValid)
    }
    

    【讨论】:

    • 并检查 OncurrentViewPropertyChanged 中的属性是否为“IsValid”。 (在 eventargs e 中)
    • @Klamsi:是的,这也是一件好事。我编辑了我的答案以包括这个。
    猜你喜欢
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多