CanSave XAML Binding to IsEnabled

CanSave XAML Binding to IsEnabled

Old forum URL: forums.lhotka.net/forums/t/10819.aspx


paul_rockerdale posted on Thursday, October 27, 2011

I'm using CSLA 4.1 with WPF, BXF and MVVM. I've got an Editable Root object containing a EditableChildList (BusinessListBase). I have a rule in the editable root that checks for duplicates in a list. The rule is triggered when child is changed using the OnChildChangded event.

        protected override void OnChildChanged(Csla.Core.ChildChangedEventArgs e)
       {
            base.OnChildChanged(e);
            BusinessRules.CheckRules(UserPositionEdit.DuplicateExistsProperty);
        }

The rule works fine. However in the ViewModel at the end of adding the "rouge child" Action the model.IsSavable property is correctly False but the CanSave property is still True. If another child is added the CanSave property catches up and is set to False. I don't get an issue when deleting a rouge child the CanSave and IsSavable work fine.

viewmodel method below.

        public void AddUserPosition(Csla.Xaml.TriggerAction triggerAction, Csla.Xaml.ExecuteEventArgs args)
        {
            Position pos = (Position)args.MethodParameter;
                var item = Model.UserPositions.AddNew();
                item.SetPosition(pos);
              
        }

A couple of thoughs are, 1) I set the values in the viewmodel and not the view. And 2) I have UoW View model and my edit view model is bound througth this.

I'm currently working round th issue by added my own CanSave ot my viewmodel binding to that e.g.

                MyCanSave = Model.IsSavable;
                OnPropertyChanged("MyCanSave");

StefanCop replied on Thursday, October 27, 2011

I think you need to raise an event right after the CheckRules, such that the ViewModelBase will update its properties. As far as I know, there are these events triggering an update:

Basically any change notification should work.

Especially if your BusinessRules changes values (OutputProperties), you also need to notify. And there are several options:

 

paul_rockerdale replied on Thursday, October 27, 2011

That has worked perfectly. Smile

I chose...

protected override void OnChildChanged(Csla.Core.ChildChangedEventArgs e)
{
 //base.OnChildChanged(e);
 BusinessRules.CheckRules(UserPositionEdit.DuplicateExistsProperty);
 OnPropertyChanged(UserPositionEdit.DuplicateExistsProperty);
}

Thanks.

 

 

markdesouza replied on Friday, October 28, 2011

Can you elaborate more about the code and the parameters used in it? 

 

  download vpn

paul_rockerdale replied on Friday, October 28, 2011

I have list of positions in a company and my app can give one or more positions to a user. So I have a readonly list of positions, to select a position and I also have an editable object that contains a user with an editable child list of positions they have.

In the xaml I have the following lines. The Save button is bound to my viewmodel  and in my viewmodel uses Csla.Xaml.ViewModel<UserPositionEdit>. So I can now bind to the CanSave method in the viewmodel.

 

CollectionViewSource x:Key="UserPositionEditViewSource" d:DesignSource="{d:DesignInstance my:UserPositionEditViewModel, CreateList=True}" />

<

 

 

Button DataContext="{Binding Path=UserPositionEditViewModel}" Content="Save" Name="SaveButton" IsEnabled="{Binding Path=CanSave}"/>

<

 

 <csla:TriggerAction DataContext="{Binding Path=UserPositionEditViewModel}" TargetControl="{Binding ElementName=AddPositionButton}" MethodParameter="{Binding ElementName=positionsListView, Path=SelectedItem}" MethodName="AddUserPosition"/>

In the viewmodel the method below adds a child position object to the list. The AddNew adds a new position to the list but it's blanks so I call SetPosition to add the Position I'm giving to the user.

        public void AddUserPosition(Csla.Xaml.TriggerAction triggerAction, Csla.Xaml.ExecuteEventArgs args)
        {
            Position pos = (Position)args.MethodParameter;
                var item = Model.UserPositions.AddNew();
                item.SetPosition(pos);
              
        }

When a child is added the OnChildChangedEvent is fired and I capture this is the parent object. This event is explained in Rocky's ebook. I can then run the rule on the parent object that uses a LINQ query to discover any duplicates. I created a property on the parent object that's called DuplicateExists. I call on PropertyChanged to refresh the binding after the rule is run

        protected override void AddBusinessRules()
        {
            base.AddBusinessRules();
            BusinessRules.AddRule(new DuplicatedPositionsExist(DuplicateExistsProperty) { Priority = 0 });
        }

        protected override void OnChildChanged(Csla.Core.ChildChangedEventArgs e)
       {
            //base.OnChildChanged(e);
            BusinessRules.CheckRules(UserPositionEdit.DuplicateExistsProperty);
            OnPropertyChanged(UserPositionEdit.DuplicateExistsProperty);

        }

        private class DuplicatedPositionsExist: Csla.Rules.BusinessRule
        {
          //insert rule here to find duplicated
      }

Copyright (c) Marimer LLC