There are three considerations here:
Consideration 1: The property has no change notification
Some data bindings may be evaluated during the InitializeComponent() call, and others are evaluated later. You are requesting the ability to set CanSeePhotos after InitializeComponent() has already returned. If don't have any change notification, any binding evaluated during InitializeComponent() will have the original value and won't be update. Any binding evaluated afterwards (such as at DataBind priority) will have the new value. To make this work in all cases you need some kind of change notification.
Using a NET Framework property declared with "{ get; set; }" won't work because the property has no mechanism to notify anyone if its value is changed. There are actually two very sneaky ways to get notification from a standard NET Framework property (MarshalByRefObject and IL rewriting) but they are much too complex for your situation.
Consideration 2: The property is static
NET Framework has several property change notification mechanisms (DependencyProperty, INotifyPropertyChanged, etc) but none of the built-in mechanisms support change notification on static properties. So you can't use a static property for this without creating a new mechanism for signaling changes (for example, you could have an object that wraps the property).
Consideration 3: DataTriggers share a single Binding
When setting Visibility you are constructing a new Binding each time, so it gets the latest value of LoggedInUser.CanSeePhotos.
When creating the DataTrigger, WPF constructs a single Binding when the trigger is loaded and uses it for every object. This Binding is constructed when the resource dictionary containing the DataTrigger is loaded, which is probably at app startup, so it will always get the default value for CanSeePhotos. This is because Source= assigns an actual object into the binding (its computation is not deferred). So every Binding is getting constructed with either Source=true or Source=false.
Recommended Solution
Use a DependencyObject with a DependencyProperty and reference it from a static property, like this:
public class LoggedInUser : DependencyObject
{
// Singleton pattern (Expose a single shared instance, prevent creating additional instances)
public static readonly LoggedInUser Instance = new LoggedInUser();
private LoggedInUser() { }
// Create a DependencyProperty 'CanSeePhotos'
public bool CanSeePhotos { get { return (bool)GetValue(CanSeePhotosProperty); } set { SetValue(CanSeePhotosProperty, value); } }
public static readonly DependencyProperty CanSeePhotosProperty = DependencyProperty.Register("CanSeePhotos", typeof(bool), typeof(LoggedInUser), new UIPropertyMetadata());
}
This class will always have one instance and that instance will be available as LoggedInUser.Instance. So it is somewhat like a static class. The difference is, LoggedInUser.Instance has a DependencyProperty, so when you modify the property it can notify any interested parties. WPF's Binding will register for this notification, so your UI will be updated.
The code above would be used like this in XAML:
Visibility="{Binding CanSeePhotos, Source={x:Static LoggedInUser.Instance}, Converter=...
In your code-behind if you need to access CanSeePhotos it would be, for example:
LoggedInUser.Instance.CanSeePhotos = true;