Page 1 of 1

Visibility binding on a UserControl used as a subview not working

Posted: 25 Sep 2017, 15:42
by Gwynneth
Hello,

As the title states I'm having some trouble with binding the Visibility property on a UserControl used as a subview. I'm using Unity 2017.1.1f1 and NoesisGUI 2.1.0b4.
I have the following code for a parent view:
<UserControl x:Class="Assets.Views.MainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:views="clr-namespace:Assets.Views"
             DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>


        <Button Grid.Row="0" Content="{Binding ButtonContent}" Width="150" Margin="5"
                VerticalAlignment="Center" HorizontalAlignment="Center"
                Command="{Binding ToggleVisibilityCommand}"/>


        <views:SubView Grid.Row="1" Visibility="{Binding SubViewVisibility}"/>


        <Button Grid.Row="2" Content="Visibility Button" Width="150" Margin="5"
                VerticalAlignment="Center" HorizontalAlignment="Center"
                Visibility="{Binding SubViewVisibility}"/>



    </Grid>
</UserControl>
It uses the following ViewModel:
using Assets.Source.Shared.Commands;
using Noesis;

namespace Assets.ViewModels {
    public class MainViewModel : ViewModelBase {


        private Visibility _subViewVisibility = Visibility.Collapsed;
        public Visibility SubViewVisibility {
            get { return _subViewVisibility; }
            set { SetProperty(ref _subViewVisibility, value); }
        }


        private string _buttonContent = "Toggle visibility...";
        public string ButtonContent {
            get { return _buttonContent; }
            set { SetProperty(ref _buttonContent, value); }
        }



        #region ToggleVisibilityCommand


        public VoidRelayCommand ToggleVisibilityCommand => new VoidRelayCommand(ToggleVisibilityCommand_Execute);


        private void ToggleVisibilityCommand_Execute(object p) {
            SubViewVisibility = _subViewVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
        }


        #endregion


    }
}
The view of the SubView usercontrol is only a simple button as follows:
<UserControl x:Class="Assets.Views.SubView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>


        <Button Grid.Row="0" Content="{Binding ButtonContent}" Width="150" Margin="5"
                VerticalAlignment="Center" HorizontalAlignment="Center"/>
        
        
        
    </Grid>
</UserControl>
The code-behind of this UserControl:
using Assets.ViewModels;
using Noesis;

namespace Assets.Views {
    public class SubView : UserControl {


        #region Properties


        /// <summary>
        /// The ViewModel this View is bound to through it's DataContext.
        /// </summary>
        /// <returns></returns>
        public SubViewModel ViewModel {
            get { return (SubViewModel)DataContext; }
            set { DataContext = value; }
        }


        #endregion


        #region Constructors + Initialization


        public SubView() {
            InitializeComponent();
        }


        /// <summary>
        /// Loads the XAML this code-behind file associates with.
        /// </summary>
        private void InitializeComponent() {


            GUI.LoadComponent(this, "Assets/Views/SubView.xaml");

            ViewModel = new SubViewModel();

        }


        #endregion


    }
}
Everything loads fine and clicking the first button successfully toggles the Visibility property in the MainViewModel. The 3rd button properly reflects this change. However, the SubView UserControl will always stay visible. If I don't use a binding and load the MainView with either Collapsed or Visible set for the SubView it properly shows the SubView as either collapsed or visible. Am I missing something crucial for the Visibility property to work?

Re: Visibility binding on a UserControl used as a subview not working

Posted: 26 Sep 2017, 11:06
by Gwynneth
Problem solved! The DataContext binding in the SubView should not be on the UserControl but on the Grid. Otherwise the Visibility binding gets redirected to the new ViewModel. Secondly, in the SubView code-behind the ViewModel property should not set the DataContext anymore but a different backing field.

Re: Visibility binding on a UserControl used as a subview not working

Posted: 29 Sep 2017, 01:50
by sfernandez
I'm marking this as solved, thanks for sharing the solution.