Search code examples
c#wpfmvvmdatacontext

Visibility property not working if i set datacontext and vice versa


I want a user control to gets visible whenever menu is selected.

Whenever user clicks the vision menu, the AV_Credentials user control is shown. But i am unable to do datacontext for the new user control.

Menu.xaml

<UserControl x:Class="Connector.Views.Menu"
         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:local="clr-namespace:Connector.Views"
         xmlns:menuViewModel="clr-namespace:Connector.ViewModel.Menu"
         xmlns:ViewModel="clr-namespace:Connector.ViewModel.AV_Credentials"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="350">
<UserControl.DataContext>
    <menuViewModel:Menu_ViewModel/>
</UserControl.DataContext>
<Grid>
    <StackPanel>
        <Menu HorizontalAlignment="Stretch" VerticalAlignment="Top" >
            <MenuItem Header="Credentials">
                <MenuItem Header="vision"  Command="{Binding Vision}"/>
                <MenuItem Header="NOP" Command="{Binding NOP}"/>
            </MenuItem>
            <MenuItem Header="Sync"/>
        </Menu>
        <local:AV_Credentials Visibility="{Binding Path=AVCred}" DataContext="{Binding AV_Context}"/>
    </StackPanel>
</Grid>

Menu_ViewModel.cs

class Menu_ViewModel : INotifyPropertyChanged
{
    private AV_Credentials_ViewModel _av_Context;
    public AV_Credentials_ViewModel AV_Context
    {
        get
        {
            if(_av_Context == null)
            {
                _av_Context = new AV_Credentials_ViewModel();
            }
            return _av_Context;
        }
    }

    private Visibility _cred = Visibility.Hidden;
    public Visibility Cred
    {
        get
        {
            return _cred;
        }
        set
        {
            _cred = value; OnPropertyChanged("Cred");
        }
    }

    private ICommand mUpdater;
    public ICommand vision
    {
        get
        {
            if (mUpdater == null)
                mUpdater = new Updater(this);
            return mUpdater;
        }
        set
        {
            mUpdater = value;
        }
    }

    private class Updater : ICommand
    {
        private Menu_ViewModel obj;
        public Updater(Menu_ViewModel _obj)
        {
            obj = _obj;
        }
        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            obj.ShowAVCred();
        }

        #endregion
    }

    public void ShowAVCred()
    {
        Cred = Visibility.Visible;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

What i am trying t achieve is -

  1. The menu will be blank.
  2. When the user selects vision from the menu, the usercontrol will be shown in the menu.
  3. There user will provide some data.

Whats Wrong

The visibility part is working fine, but the buttons and textboxes in the usercontrol is not working. If i assign datacontext, the button and textboxes are working, but the visibility is not working.

If required i can share the AV_Credential .xaml and .cs

Sorry for bad english


Solution

  • If i assign datacontext, the button and textboxes are working, but the visibility is not working.

    Add "AV_Context." to the binding paths in AV_Credentials.xaml, e.g.:

    <TextText Text="{Binding AV_Context.YourProperty}" />
    

    This should work since the DataContext of the AV_Credentials control is a Menu_ViewModel and this type has a AV_Context property.

    You should not explicitly set the DataContext of the UserControl because then the binding to the Menu_ViewModel's Cred property will fail as you have already discovered.

    The other option would be to specify an explicit source for the Visibility binding:

    <local:AV_Credentials Visibility="{Binding Path=DataContext.Cred, RelativeSource={RelativeSource AncestorType=UserControl}}" 
                          DataContext="{Binding AV_Context}"/>