WPF MVVM-监视对绑定对象的更改(例如,如果IsDirty则启用保存)



在WPF中,使用MVVM模式(并使用MVVMLight工具包),我有一个显示产品可编辑字段的用户控件。此UC绑定到列出所有产品的组合框中的选定值。

这一切都很好,但在我的Product类中,我有一个名为IsDirty的布尔字段,当Product上的任何属性更新时,该字段都设置为true每当所选产品(在用户控件中)的IsDirty属性为true时,我希望在主视图中启用保存按钮我不知道如何让IsSaveEnabled属性"监视"SelectedProduct中的更改(基本上是当它变脏时)。

我可以通过使用事件处理程序来实现这一点,但这会将一个事件附加到所选的每个产品上,看起来又脏又笨重。这是我在如何正确监视绑定对象的更改方面缺少的东西吗?

产品.xaml (部分)

<Grid DataContext="{Binding Source={StaticResource ProductsViewModel}}">
    <StackPanel>
        <ComboBox x:Name="ProductsComboBox" 
                  ItemsSource="{Binding Path=ProductList}" 
                  DisplayMemberPath="Name" 
                  SelectedItem="{Binding SelectedProduct}" />
        <uc:Product DataContext="{Binding SelectedItem, ElementName=ProductsComboBox}" />
        <Button Content="Save" IsEnabled="{Binding IsSaveEnabled}" Click="Button_Click" />
    </StackPanel>
</Grid>

ProductsViewModel.cs(部分)

public bool IsSaveEnabled
{
    get { return SelectedProduct.IsDirty; }
}
public ProductViewModel SelectedProduct
{
    get { return _selectedProduct; }
    set { 
        // I can use the next line, but it seems really clunky and creates a ton of event listeners
        // value.PropertyChanged += SelectedProduct_PropertyChanged;
        Set(() => SelectedProduct, ref _selectedProduct, value); 
        }
}
// This is the event handler that seems bad form and a duplication of functionality that is already in the Product class
//void SelectedProduct_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
//    {
//        SelectedProperty.IsDirty = true;
//        RaisePropertyChanged(() => IsSaveEnabled);
//    }

您可能应该使用命令:

    public static RoutedCommand Command_Save = new RoutedCommand ( );
    void Command_Save_Executed ( object sender, ExecutedRoutedEventArgs e )
    {
         // save the product
    }
    void Command_Save_CanExecute ( object sender, CanExecuteRoutedEventArgs e )
    {
        e.CanExecute = SelectedProduct.IsDirty;
    }

XAML:

<Button Content="Save" Command="{x:Static MY:ProductsControl.Command_Save }" />

并将其与对照结合(在ctor或xaml中):

            this.CommandBindings.Add( new CommandBinding( Command_SaveAs,
                                                      Command_SaveAs_Executed,
                                                      Command_SaveAs_CanExecute ) );

命令基础结构将调用CanExecute事件处理程序来禁用/启用按钮。

我会这样做:

public class ProductsViewModel
{
    private bool _isSaveEnabled;
    public bool IsSaveEnabled
    {
        get { return _isSaveEnabled; }
        private set
        {
            _isSaveEnabled = value;
            RaisePropertyChanged();
        }
    }
    public ProductViewModel SelectedProduct
    {
        get { return _selectedProduct; }
        set 
        { 
            if (value != _selectedProduct)
            {
                // unsubscribe from old selected product changes
                //
                _selectedProduct.PropertyChanged -= OnPropertyChanged;
                // subscribe to new selected product changes
                //
                value.PropertyChanged += OnPropertyChanged;
                _selectedProduct = value;
                RaisePropertyChanged();
            }
        }
    }
    private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        SelectedProperty.IsDirty = true;
        IsSaveEnabled = SelectedProperty.IsDirty;
    }   
}

您之所以看到这么多事件处理程序,是因为每次所选产品发生更改时,您都会订阅一个新的事件处理程序。你只想做一次,所以在订阅新的之前,请确保取消订阅旧的。此外,不需要为IsSaveEnabled执行RaisePropertyChanged,只需在其setter中引发事件即可。

相关内容

最新更新