0

I have a view in XAML where I have a listbox, and a selection in that listbox populates an area to the side with properties from the selected instance of the ChildViewModel. I have a few buttons in the ChildView that are connected to commands in the ChildViewModel. Before I make a selection from the parent listbox, these buttons do nothing as expected. How could I keep these buttons hidden until a selection selection in the parent listbox is made, thus creating an instance of the ChildViewModel.

I know how I could accomplish this if these buttons were part of the parent view by binding the visibility of these buttons to {Binding SelectedItem, ElementName=listBoxName}. However, I am having a hard time accomplishing this within the ChildView because I do not have access to (and do not want to be dependent on) the element from the parent view. Please help me accomplish this, preferably purely within the XAML code.

H.B.
  • 166,899
  • 29
  • 327
  • 400
sebo
  • 1,584
  • 4
  • 16
  • 19
  • I found the solution I was looking for in ChrisWue's answer here http://stackoverflow.com/questions/6313102/wpf-how-to-bind-to-datacontext-existance – sebo Jul 26 '12 at 14:43

3 Answers3

2

You should be able to just check if the datacontext of the childview is null (i.e. no ChildViewModel set). If it is null hide the buttons.

<Button Click="Button_Click" Content="bah">
        <Button.Style>
            <Style TargetType="Button">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext}" Value="{x:Null}" >
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>

Set the ancestor to whatever container is holding your child view

Nogusta
  • 909
  • 5
  • 10
0

One way to tackle this is to do the signalling based on the ViewModel properties and bindings, and a ValueConverter to manage the Visibility.

Given a Parent View & View Model, that will have child View's with their own View Models, and the parent's VM is responsible for child VM's:

Parent View Model: Contains a "SelectedItem" property (Named suitably for context) that the listbox's SelectedItem is bound to. Within the Setter, set a boolean property on the child's VM. (I.e. ParentItemSelected) The Child's controls Visibility property is bound to ParentItemSelected with a value converter that converts boolean values to a suitable Visibility value.

If the parent and child views share a VM, then the same thing works, but just base visibility on whether the "SelectedItem" is null or not. (or can use a similar Boolean property.)

Steve Py
  • 26,149
  • 3
  • 25
  • 43
  • If you are loading child views and are trying to follow MVVM in a pure fashion, then I agree that signaling from the ViewModel is the way to go. I don't know what MVVM framework (if any) is being used, but MVVMLight has a brilliant loosely coupled Messenger class that is perfect for this. – EdFred Jul 26 '12 at 03:26
  • I don't understand how this will work. Any boolean properties that exist within the child VW will not be initialized until after the constructor is called (which happens when the listbox item is selected) – sebo Jul 26 '12 at 14:16
0

As suggested by EdFred you could use MVVMLight and its Messenger functionality to decouple communication between dependent objects. Here is an example how you can do that.

If you are not using any MVVM framework, you could still expose an event on the parent which can be subscribed from the child view model. when the selection changes in the parent, you can perform whatever action you wish to perform on the child view model.

Nilesh Gule
  • 1,511
  • 12
  • 13
  • I am not using any MVVM framework. My problem is that the child instance is not created yet when the gui starts up, so anything I perform in the child view model does not get done until an item is actually selected. – sebo Jul 26 '12 at 14:11