Binding to static property

WpfXamlData Binding

Wpf Problem Overview


I'm having a hard time binding a simple static string property to a TextBox.

Here's the class with the static property:

public class VersionManager
{
    private static string filterString;
    
    public static string FilterString
    {
        get { return filterString; }
        set { filterString = value; }
    }
}

In my xaml, I just want to bind this static property to a TextBox:

<TextBox>
    <TextBox.Text>
        <Binding Source="{x:Static local:VersionManager.FilterString}"/>
    </TextBox.Text>
</TextBox>

Everything compiles, but at run time, I get the following exception:

> Cannot convert the value in attribute 'Source' to object of type 'System.Windows.Markup.StaticExtension'. Error at object 'System.Windows.Data.Binding' in markup file 'BurnDisk;component/selectversionpagefunction.xaml' Line 57 Position 29.

Any idea what I'm doing wrong?

Wpf Solutions


Solution 1 - Wpf

If the binding needs to be two-way, you must supply a path.

There's a trick to do two-way binding on a static property, provided the class is not static : declare a dummy instance of the class in the resources, and use it as the source of the binding.

<Window.Resources>
    <local:VersionManager x:Key="versionManager"/>
</Window.Resources>
...

<TextBox Text="{Binding Source={StaticResource versionManager}, Path=FilterString}"/>

Solution 2 - Wpf

You can't bind to a static like that. There's no way for the binding infrastructure to get notified of updates since there's no DependencyObject (or object instance that implement INotifyPropertyChanged) involved.

If that value doesn't change, just ditch the binding and use x:Static directly inside the Text property. Define app below to be the namespace (and assembly) location of the VersionManager class.

<TextBox Text="{x:Static app:VersionManager.FilterString}" />

If the value does change, I'd suggest creating a singleton to contain the value and bind to that.

An example of the singleton:

public class VersionManager : DependencyObject {
    public static readonly DependencyProperty FilterStringProperty =
        DependencyProperty.Register( "FilterString", typeof( string ),
        typeof( VersionManager ), new UIPropertyMetadata( "no version!" ) );
    public string FilterString {
        get { return (string) GetValue( FilterStringProperty ); }
        set { SetValue( FilterStringProperty, value ); }
    }

    public static VersionManager Instance { get; private set; }

    static VersionManager() {
        Instance = new VersionManager();
    }
}

<TextBox Text="{Binding Source={x:Static local:VersionManager.Instance},
                        Path=FilterString}"/>

Solution 3 - Wpf

In .NET 4.5 it's possible to bind to static properties, read more

> You can use static properties as the source of a data binding. The > data binding engine recognizes when the property's value changes if a > static event is raised. For example, if the class SomeClass defines a > static property called MyProperty, SomeClass can define a static event > that is raised when the value of MyProperty changes. The static event > can use either of the following signatures:

public static event EventHandler MyPropertyChanged; 
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged; 

> Note that in the first case, the class exposes a static event named > PropertyNameChanged that passes EventArgs to the event handler. > In the second case, the class exposes a static event named > StaticPropertyChanged that passes PropertyChangedEventArgs to the > event handler. A class that implements the static property can choose > to raise property-change notifications using either method.

Solution 4 - Wpf

As of WPF 4.5 you can bind directly to static properties and have the binding automatically update when your property is changed. You do need to manually wire up a change event to trigger the binding updates.

public class VersionManager
{
    private static String _filterString;        

    /// <summary>
    /// A static property which you'd like to bind to
    /// </summary>
    public static String FilterString
    {
        get
        {
            return _filterString;
        }

        set
        {
            _filterString = value;

            // Raise a change event
            OnFilterStringChanged(EventArgs.Empty);
        }
    }

    // Declare a static event representing changes to your static property
    public static event EventHandler FilterStringChanged;
        
    // Raise the change event through this static method
    protected static void OnFilterStringChanged(EventArgs e)
    {
        EventHandler handler = FilterStringChanged;

        if (handler != null)
        {
            handler(null, e);
        }
    }
    
    static VersionManager()
    {
        // Set up an empty event handler
        FilterStringChanged += (sender, e) => { return; };
    }

}

You can now bind your static property just like any other:

<TextBox Text="{Binding Path=(local:VersionManager.FilterString)}"/>

Solution 5 - Wpf

There could be two ways/syntax to bind a static property. If p is a static property in class MainWindow, then binding for textbox will be:

1.

<TextBox Text="{x:Static local:MainWindow.p}" />

2.

<TextBox Text="{Binding Source={x:Static local:MainWindow.p},Mode=OneTime}" />

Solution 6 - Wpf

You can use ObjectDataProvider class and it's MethodName property. It can look like this:

<Window.Resources>
   <ObjectDataProvider x:Key="versionManager" ObjectType="{x:Type VersionManager}" MethodName="get_FilterString"></ObjectDataProvider>
</Window.Resources>

Declared object data provider can be used like this:

<TextBox Text="{Binding Source={StaticResource versionManager}}" />

Solution 7 - Wpf

If you are using local resources you can refer to them as below:

<TextBlock Text="{Binding Source={x:Static prop:Resources.PerUnitOfMeasure}}" TextWrapping="Wrap" TextAlignment="Center"/>

Solution 8 - Wpf

Right variant for .NET 4.5 +

C# code

public class VersionManager
{
    private static string filterString;

    public static string FilterString
    {
        get => filterString;
        set
        {
            if (filterString == value)
                return;

            filterString = value;

            StaticPropertyChanged?.Invoke(null, FilterStringPropertyEventArgs);
        }
    }

    private static readonly PropertyChangedEventArgs FilterStringPropertyEventArgs = new PropertyChangedEventArgs (nameof(FilterString));
    public static event PropertyChangedEventHandler StaticPropertyChanged;
}

XAML binding (attention to braces they are (), not {})

<TextBox Text="{Binding Path=(yournamespace:VersionManager.FilterString)}" />

Solution 9 - Wpf

Leanest answer (.net 4.5 and later):

    static public event EventHandler FilterStringChanged;
    static string _filterString;
    static public string FilterString
    {
        get { return _filterString; }
        set
        {
            _filterString= value;
            FilterStringChanged?.Invoke(null, EventArgs.Empty);
        }
    }

and XAML:

    <TextBox Text="{Binding Path=(local:VersionManager.FilterString)}"/>

Don't neglect the brackets

Solution 10 - Wpf

Look at my project CalcBinding, which provides to you writing complex expressions in Path property value, including static properties, source properties, Math and other. So, you can write this:

<TextBox Text="{c:Binding local:VersionManager.FilterString}"/>

Goodluck!

Solution 11 - Wpf

Another solution is to create a normal class which implements PropertyChanger like this

public class ViewProps : PropertyChanger
{
    private string _MyValue = string.Empty;
    public string MyValue
    {
        get { 
            return _MyValue
        }
        set
        {
            if (_MyValue == value)
            {
                return;
            }
            SetProperty(ref _MyValue, value);
        }
    }
}

Then create a static instance of the class somewhere you wont

public class MyClass
{
    private static ViewProps _ViewProps = null;
    public static ViewProps ViewProps
    {
        get
        {
            if (_ViewProps == null)
            {
                _ViewProps = new ViewProps();
            }
            return _ViewProps;
        }
    }
}

And now use it as static property

<TextBlock  Text="{x:Bind local:MyClass.ViewProps.MyValue, Mode=OneWay}"  />

And here is PropertyChanger implementation if necessary

public abstract class PropertyChanger : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(storage, value)) return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Solution 12 - Wpf

Suppose you have a class as follow:

public static class VersionManager 
{
    public static string FilterString;
}

You can bind your static variable in this way:

<TextBox Text = {x:Static local:VersionManager.FilterString }/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnthony BrienView Question on Stackoverflow
Solution 1 - WpfThomas LevesqueView Answer on Stackoverflow
Solution 2 - WpfAdam SillsView Answer on Stackoverflow
Solution 3 - WpfJowenView Answer on Stackoverflow
Solution 4 - WpfMattView Answer on Stackoverflow
Solution 5 - WpfKylo RenView Answer on Stackoverflow
Solution 6 - WpfGPAshkaView Answer on Stackoverflow
Solution 7 - WpfEdmund CovingtonView Answer on Stackoverflow
Solution 8 - WpfAlexei ShcherbakovView Answer on Stackoverflow
Solution 9 - WpfSeanView Answer on Stackoverflow
Solution 10 - WpfAlex141View Answer on Stackoverflow
Solution 11 - WpfneosonneView Answer on Stackoverflow
Solution 12 - WpfBilal KanjView Answer on Stackoverflow