WPF MVVM - Unable to bind Model property directly to the IsEnabled Property of Button

Sudarshan Gujar 1 Reputation point
2020-04-06T04:44:18.333+00:00

Hello Team,

Please find below View, ViewModel and Model class. I have binded collection of models (in ViewModel) to DataGrid control in the view. But based on UI selection, need to update another property in model. I am not able do to it via binding.

Actual Problem -

When combobox value gets changed on UI, we need to Enable the button. Somehow, I am not able to do it via databinding. Am I missing something ? Please help me.

View-

<UserControl x:Class="Poject.RelationshipControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">

<Grid x:Name="LayoutRoot">

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="75"/>
    </Grid.RowDefinitions>

    <StackPanel Orientation="Vertical">
       <StackPanel Orientation="Horizontal" Margin="5,10,0,0">
            <DataGridControl x:Name="DataGridData" 
                          BorderThickness="0" 
                          SelectionMode="Single"
                          GridLinesVisibility="None"
                          AutoGenerateColumns="False" 
                          MinHeight="380"
                          Width="Auto"
                          VerticalScrollBarVisibility="Auto"
                          ItemsSource="{Binding SignificantPersonData}"
                    <DataGridControl.Columns>
                    <sdk:DataGridTemplateColumn Header="Relationship" MinWidth="150">
                        <sdk:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox ItemsSource="{Binding RelationshipsToSignificantPerson, Mode=TwoWay}" 
                                      SelectedItem="{Binding SelectedRelationship, Mode=TwoWay}"
                                      Width="180" Margin="0,10,0,0"
                                      Height="30"/>
                            </DataTemplate>
                        </sdk:DataGridTemplateColumn.CellTemplate>
                    </sdk:DataGridTemplateColumn>

</DataGridControl.Columns>
</DataGridControl>
</StackPanel>
</StackPanel>

    <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
        <Button Content="cancel" Height="55" IconHeight="35"
                                  IconWidth="35" Margin="10,0,20,0" Command="{Binding CancelCommand}"
                                  Style="{StaticResource CancelButton}"/>
        <Button Content="save" Height="55"
                                  IconHeight="35" IconWidth="35"
                                  IsEnabled="{Binding ElementName=DataGridData, Path=DataContext.IsEditable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                  Margin="20,0,10,0" Command="{Binding SaveCommand}"
                                  Style="{StaticResource SaveButton}"/>
    </StackPanel>
</Grid>

</UserControl>
ViewModel -

private ObservableCollection<PersonDataModel> _significantPersonData;
public ObservableCollection<PersonDataModel> SignificantPersonData
{
get
{
return _significantPersonData;
}
set
{
_significantPersonData = value;
NotifyPropertyChanged(() => SignificantPersonData);
}
}

private void OnLoad()
{
SignificantPersonData.Add(new PersonDataModel
{
RelationshipsToSignificantPerson = relationshipsLibraryValues.ToList(),
SelectedRelationship = relationshipsLibraryValues.FirstOrDefault(x => x.stl_value == _relationship),
IsEditable = false
});
}

Model -

public class PersonDataModel : INotifyPropertyChanged
{
private List<stl_libraryvalueModel> _relationshipsToSignificantPerson;
public List<stl_libraryvalueModel> RelationshipsToSignificantPerson
{
get { return _relationshipsToSignificantPerson; }
set
{
_relationshipsToSignificantPerson = value;
NotifyPropertyChanged(() => RelationshipsToSignificantPerson);
}
}

    private stl_libraryvalueModel _selectedrelationship;
    public stl_libraryvalueModel SelectedRelationship
    {
        get { return _selectedrelationship; }
        set
        {
            _selectedrelationship = value;
            IsEditable = true;
            NotifyPropertyChanged(() => SelectedRelationship);
            NotifyPropertyChanged(() => IsDetailsVisible);
        }
    }


    private bool _isEditable;
    public bool IsEditable
    {
        get
        {
            return _isEditable;
        }
        set
        {
            _isEditable = value;
            NotifyPropertyChanged(() => IsEditable);
        }
    }
}

Thanks.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,671 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-06T19:40:25.637+00:00

    Hi, use TrulyObservableCollection to detect changes in data objects. ViewModel consuming PropertyChanged event can check data objects and enable/disable button:

      /// <summary>
      /// Implements the "ItemPropertyChanged" Event for a ObservableCollection
      /// </summary>
      /// <typeparam name="T"></typeparam>
      /// <seealso cref="System.Collections.ObjectModel.ObservableCollection{T}" />
      public sealed class TrulyObservableCollection<T> : ObservableCollection<T>
      where T : INotifyPropertyChanged
      {
        /// <summary>
        /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
        /// </summary>
        public TrulyObservableCollection() => CollectionChanged += FullObservableCollectionCollectionChanged;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="TrulyObservableCollection{T}"/> class.
        /// </summary>
        /// <param name="pItems">The p items.</param>
        public TrulyObservableCollection(IEnumerable<T> pItems) : this()
        {
          foreach (var item in pItems) this.Add(item);
        }
    
        /// <summary>
        /// Fulls the observable collection collection changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
        private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
          if (e.NewItems != null) foreach (Object item in e.NewItems) ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged;
          if (e.OldItems != null) foreach (Object item in e.OldItems) ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged;
        }
    
        /// <summary>
        /// Items the property changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
        private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) => OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender)));
      }
    
    0 comments No comments