Ken Schmitt
Ken Schmitt

Reputation: 1

Unable to bind XAML button visibility with C# view model private visibility variable

I want to bind button visibility in a XAML file to a private Visibility variable in the associated C# view model code. When the code is run, the button continues to show and not hide as defined in the private visibility variable. I have tried many things after reading many responses on the internet to similar problems.

The following run-time error seen in the output window has stopped product development:

System.Windows.Data Error: 40 : BindingExpression path error: 'SaveCalButtonVisibility' property not found on 'object' ''CalibrationSet' (HashCode=40040273)'. BindingExpression:Path=SaveCalButtonVisibility; DataItem='CalibrationSet' (HashCode=40040273); target element is 'Button' (Name=''); target property is 'Visibility' (type 'Visibility')

The current object is CalibrationSetList and for some reason, it seems to try to bind the XAML Save Calibration Button Visibility property to DataItem=CalibrationSet Path=SaveCalButtonVisibility path. I believe that this should bind to the DataItem=CalibrationSetList Path=SaveCalButtonVisibility path to work properly. I am at a loss to complete this binding.

The development environment is Microsoft Visual Studio 2010 with Infragistics 2013.2. The XAML and C# code are shown below with unrelated code left out. The code is written following the MVVM pattern, WPF, and PRISM 4.0

Any help, suggestions, or continuing dialog is greatly appreciated.

XAML Code:

<!-- CalibrationSetList.xaml -->

<UserControl 
    x:Class="Method.Control.CalibrationSetList"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:I18N="clr-namespace:I18N;assembly=I18N" 
    xmlns:I18NStrings="clr-namespace:I18N.Strings;assembly=I18N.Strings"
    xmlns:Conv="clr-namespace:Converters;assembly=Converters"
    mc:Ignorable="d" 
    xmlns:Local="clr-namespace:Method.Control"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:AuthInfrastructure="clr-namespace:Authorization.Components;assembly=Authorization.Components"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"    >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"  />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Visibility="{Binding Path=CalibrationSetListControl}">
            <Grid Visibility="{Binding Path=CalibrationSetListVisibility}"  >
                <Grid.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
                </Grid.Resources>

                <DataGrid EnableRowVirtualization="False" 
                          EnableColumnVirtualization="False" 
                          IsReadOnly="True" 
                          ItemsSource="{Binding CalibrationCollection, Mode=TwoWay}" 
                          SelectedValue="{Binding Path=SelectedCalibrationSetValue}" 
                          HorizontalGridLinesBrush="Transparent" 
                          VerticalGridLinesBrush="Transparent" Margin="30">

                    <DataGrid.Columns>

<!--…………………………………->

                        <!--Save Calibration button-->
                        <DataGridTemplateColumn Width="125">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>

                                    <Button  Style="{DynamicResource CustomButton}" 

                                         Visibility="{Binding Path=SaveCalButtonVisibility,Mode=TwoWay,
                                                             diag:PresentationTraceSources.TraceLevel=High}"

                                         HorizontalAlignment="Center" 
                                         VerticalAlignment="Center" 
                                         Command="{Binding Path=DataContext.SaveCalibrationClick,
                                                                RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}" 
                                         CommandParameter="{Binding}" >
                                        <Button.Content>
                                            <MultiBinding Converter="{Conv:StringToLocalizedString ResourceKey=SaveCalibration}">
                                                <Binding  RelativeSource="{RelativeSource AncestorType=UserControl}" 
                                                                 Path="DataContext.SelectedLanguage"></Binding>
                                            </MultiBinding>
                                        </Button.Content>
                                        <i:Interaction.Behaviors>
                                            <AuthInfrastructure:ControlBehavior x:Name="btnCalibrationSetSave" 
                                                          VMBounded="CalibrationSetSave" ModuleName="Calibration" />
                                        </i:Interaction.Behaviors>
                                    </Button>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>

                    </DataGrid.Columns>
                </DataGrid>
            </Grid>
<!--…………………………………->
        <!--Calibration Set Control-->
        <Grid Visibility="{Binding Path=CalibrationSetControl}" HorizontalAlignment="Left" Width="762">
            <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Local:CalibrationSet 
                Grid.Row="0" 
                Grid.Column="0" 
                DataContext="{Binding CalibrationSetViewModelContext,Mode=TwoWay}" 
                ScrollViewer.HorizontalScrollBarVisibility="Auto" 
                ScrollViewer.VerticalScrollBarVisibility="Auto">
            </Local:CalibrationSet>
        </Grid>
        <!--End Calibration Set Control-->
    </Grid>
</UserControl>

Matching C# code:

// CalibratonSetListViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using DataStructures;
using Framework;
using Method.Component;
using Method.Control.Calibration.Interface;
using Microsoft.Practices.Prism.Regions;
using EventAggregation;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.ServiceLocation;
using ViewModel.Base;
using Microsoft.Practices.Prism;
using CustomMessageBox;
using Chromatogram.DataDisplay.Control;

namespace Method.Control
{
    /// <summary>
    /// Set or Get CalibrationSetViewModelContext
    /// </summary>
    public class CalibrationSetListViewModel : ViewModelBase
    {
        #region Variables

//………………………………

        /// <summary>
        /// Save Cal Button Visibility
        /// </summary>
        private Visibility m_SaveCalButtonVisibility;

//………………………………

        #endregion

        #region Properties

//………………………………

        /// <summary>
        /// Set or Get Save Cal Button Visibility 
        /// </summary>
        public Visibility SaveCalButtonVisibility
        {
            get
            {
                return m_SaveCalButtonVisibility;
            }
            set
            {
                m_SaveCalButtonVisibility = value;
                OnPropertyChanged(() => SaveCalButtonVisibility);
            }
        }
//………………………………
       #endregion

        #region Constructor

        /// <summary>
        ///  Initializes new instance of MethodListViewModel
        /// </summary>
        /// <param name="methodId">MethodId</param>
        /// <param name="peakDataProvider">PeakDataProvider</param>
        public CalibrationSetListViewModel(int methodId, IPeakDataProvider peakDataProvider)
        {
            try
            {
                m_DataDisplayOfflineViewModel = new DataDisplayOfflineViewModel(true);  // gain access to member functions

                m_MethodId = methodId;
                m_PeakDataProvider = peakDataProvider;
                m_CalibrationSetListVisibility = Visibility.Visible;
                m_CreateButtonVisibility = Visibility.Collapsed;
                m_SaveCalButtonVisibility = Visibility.Collapsed;

                GetCalibrationsList();
                CreateCalibrationClick = new RelayCommand(parm => this.CreateCalibration());
                DeleteCalibrationClick = new RelayCommand(this.DeleteCalibration);
                SaveCalibrationClick = new RelayCommand(this.SaveCalibration);

                CalibrationDetailsClick = new RelayCommand(this.CalibrationDetails);
                CalibrationResultClick = new RelayCommand(this.CalibrationResult);

                //Publish menu clicked event
                m_EventAggregator = ServiceLocator.Current.GetInstance<IEventAggregator>();
                MenuHomePage menuHomePage = MenuHomePage.CalibrationSet;
                m_EventAggregator.GetEvent<ToolBarChange>().Publish(menuHomePage);

                SetCalibrationVisibility();

                //Subscribe CreateNewCalibration method
                m_CreateNewCalibration = m_EventAggregator.GetEvent<ToolBarCreateNewCalibrationEvent>();
                m_CreateNewCalibrationToken = m_CreateNewCalibration.Subscribe(createNewCalibration);

            }
            catch (Exception)
            {
                throw;
            }
        }

        #endregion

        #region Public Methods
//………………………………
      #endregion

      #region Public Methods
//………………………………
      #endregion

      #region Private Methods


      /// <summary>
      /// Create New CalibrationSet
      /// </summary>
      /// <returns></returns>
      private Entities.CalibrationSet CreateNewCalibrationSet()
      {
          Entities.CalibrationSet newCalibrationSet = new Entities.CalibrationSet();
          newCalibrationSet.CalibrationSetId = 0;
          newCalibrationSet.CalibrationSetNumber = 1;
          newCalibrationSet.AmountUnits = 2;
          return newCalibrationSet;
      }
//………………………………
        #endregion

    }
}

Upvotes: -1

Views: 764

Answers (1)

slimbofat
slimbofat

Reputation: 388

Assuming your CalibrationSetList binds to a CalibrationSetListViewModel (which might not, it's hard to tell) the problem would be different DataContexts between the UserControl (which would be the CalibationSetListViewModel) and a cell in the grid (which would be an individual item in the collection that the grid is bound to).

To bind these properties (which are by default bound to properties of the individual items of the collection) to the top-level ViewModel, use:

{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, 
         Path=DataContext.SaveCalButtonVisibility }

Hope that helps

Upvotes: 0

Related Questions