13

I've an WPF application where tried to implement MVVM pattern and Prism 2. I have a Usercontrol which has subscribed to an event fired from another Usercontrol. I would like to toggle visibility of few child elements in the subscribing control. Events are fired properly, even I am successfully able to bind data to some elements. How do I bind Visibility or any style property for that matter with the ViewModel and change them dynamically.

Raj
  • 4,405
  • 13
  • 59
  • 74

3 Answers3

27

You can have a boolean property in your ViewModel and bind that property to the Visibility property of your controls. Since you will be asigning a boolean value and the Visibility property is expecting a Visibility enumeration value, you will have to use the BooleanToVisibilityConverter converter to make the conversion,

<Style.Resources>
     <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</Style.Resources>

<Image Visibility="{Binding Path=ShowImage, 
                    Converter={StaticResource booleanToVisibilityConverter}}"/>

Hope this helps.

Ezequiel Jadib

Tseng
  • 61,549
  • 15
  • 193
  • 205
Ezequiel Jadib
  • 14,767
  • 2
  • 38
  • 43
  • Somehow this didn't work for me. I declared converter in Usercontrol.Resources section and used bindings as you have explained in the comment. – Raj Sep 13 '09 at 03:04
10

Although adding a Boolean property and using a value converter works, I would recommend adding a property of type Visibility to your ViewModel, e.g.

public Visibility ImageVisibility
{
    get { return shouldShowImage ? Visibility.Visible : Visibility.Collapsed }
}

The advantage of this method is you don't need to write a converter for every property you want to express in a visual way (e.g. for a stock level that turns a label red when it drops below 10, you could have a converter you use once or just expose a StockLabelBrush property from your VM)

Darren
  • 4,408
  • 4
  • 39
  • 57
  • While this answer is elegant, there's a problem with it. If the program changes `shouldShowImage`, that change is not sent to the view. – James Mar 19 '14 at 14:35
  • 2
    That is true, but there are a couple of ways to handle the problem. You can either handle the `PropertyChanged` event from `shouldShowImage` and raise a new `PropertyChanged` event, or only allow access to `shouldShowImage` through a wrapper property that raises events for both properties. – Darren Mar 19 '14 at 16:52
  • 1
    I can see two things going on here, (i) I decide whether something is true or false (which seems appropriate for a VM to do) and (ii) I take that boolean value and decide whether some control should be visible or not (which seems appropriate for the View. I'd have thought using a converter here would be ideal in terms of keeping the V/VM boundary clean. – PeteH Dec 06 '18 at 10:59
  • @PeteH, the difference between a ViewModel and a Model is that the ViewModel is concerned with what is displayed in the view. Without that logic in the ViewModel you just have a Model. Also, it is very easy to test the element on the view becomes visible when the Boolean changes if the logic is in the VM. – Darren Dec 06 '18 at 16:00
  • that's bad because if you port your code to different .Net technology e.g. MAUI this wouldn't work, whereas boolean approach is more portable – Piotr Golacki Apr 19 '23 at 10:11
2

There's a simple solution for people who run into this issue.

In your view model, create a "Visibility" property like so:

public Visibility ShowModifyButtons
    {
        get { return (Visibility)GetValue(ShowModifyButtonsProperty); }
        set { SetValue(ShowModifyButtonsProperty, value); }
    }

public static readonly DependencyProperty ShowModifyButtonsProperty =
        DependencyProperty.Register("ShowModifyButtons", typeof(Visibility), typeof(FileMatchViewModel),
        new UIPropertyMetadata(Visibility.Collapsed));

In your XAML, bind to it like so:

 <Button Focusable="False" Content="Save" Width="100" Margin="10" Visibility="{Binding ShowModifyButtons}"/>

Now, from your view model, you can set ShowModifyButtons to Visibility.Collapsed or Visibility.Visible as needed.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
James
  • 954
  • 2
  • 13
  • 27