Can I set a DataContext to a static class?
Asked Answered
S

3

9

I've a static class which reads information from the application assembly.

I've declared it static since the class needs no instance declaration and will only ever be read directly from, application-wide. I have a control with several labels that I would like to use to display some of this information.

How can I go about setting the controls DataContext equal to the class?

Code:

/// <summary>
/// Class for Reading Program Information.
/// </summary>
public static class ProgramInfo {
    private static Assembly ProgramAssembly = Assembly.GetEntryAssembly( );

    /// <summary>
    /// Get Program Name
    /// </summary>
    public static string ProgramName {
        get { return ProgramInfo.ProgramAssembly.GetCustomAttribute<AssemblyProductAttribute>( ).Product; }
    }

    /// <summary>
    /// Get Program Build Date
    /// </summary>
    public static DateTime BuildDate {
        get { return File.GetLastWriteTime( ProgramInfo.ProgramAssembly.Location ); }
    }

    /// <summary>
    /// Get Program Version (Major.Minor)
    /// </summary>
    public static string Version {
        get {
            System.Version V = ProgramInfo.ProgramAssembly.GetName( ).Version;
            return V.Major.ToString( ) + '.' + V.Minor.ToString( );
        }
    }

    /// <summary>
    /// Get Program Build (Build.Revision)
    /// </summary>
    public static string Build {
        get {
            System.Version V = ProgramInfo.ProgramAssembly.GetName( ).Version;
            return V.Build.ToString( ) + '.' + V.Revision.ToString( );
        }
    }
}

XAML:

<UserControl x:Class="Tools.Controls.ProgramInformation"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:pi="clr-namespace:Tools.Controls">
<UserControl.DataContext>
    <pi:ProgramInfo/>
</UserControl.DataContext>
<!--Other Irrelevant Code-->
</UserControl>
Semitropical answered 10/1, 2015 at 19:47 Comment(0)
A
14

You can bind to a static field or property by using the {x:Static} binding syntax.

x:Static is used to get static fields and properties. You can set the datacontext to a static field, or property, but not to a static type.

Example below:

<DataContext Source="{x:Static prefix:typeName.staticMemberName}" />

It'd be more appropriate for you to ignore the datacontext, and just use a {x:Static binding for each value you wish to bind. For example, below would bind the program name static property:

<TextBlock Text="{Binding Source={x:Static pi:ProgramInfo.ProgramName}}" /> 
Aveyron answered 10/1, 2015 at 20:13 Comment(1)
I think that's exactly for what I'm looking.Semitropical
B
8

From the original version of the question:

I've declared it static since I will only ever need a single application-wide accessible instance of the class.

That's not what a static class is. You can never have any instance of a static class.

Although you've now changed the question to refer to there being no instances, a single instance really is probably a better idea, as binding via a data context is more geared up for instances.

What you're probably looking for is a singleton - where you can create an instance, and most of the members are instance members, but where there's guaranteed to only be a single instance.

You can make a singleton very easily:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    public static Singleton Instance { get { return instance; } }

    // Private constructor to prevent instantiation
    private Singleton() {}

    // Instance members from here onwards
}

There are various other implementation options, mind you - see my page on the topic for more examples.

Then you'd set the DataContext to refer to the singleton instance. (I assume that's easy enough in WPF - it's been too long since I've done it.)

Without that single instance, the only thing you could potentially set your DataContext to would be the type itself - and unless WPF is set up to specifically know to fetch the static members of the type which is being referenced when the context is set to a type, I can't see it working.

Bander answered 10/1, 2015 at 19:50 Comment(7)
Okay, right, I used the incorrect vernacular. I don't want any instance of the class, at all. I just want a structure through which I can access this information. Edited...Semitropical
@Will: Well then you can't set a DataContext property to be that. I suspect you really do want something with a single instance - see my edit for how to do that.Bander
Then if I implemented it in this fashion I would want no static properties within the class itself, correct?Semitropical
@Will: That's right - they'd be instance properties instead.Bander
I get this error : The type <class> does not include any accessible constructors.Semitropical
@Will: Right, so that's why I'm saying you've got to set the data context via the static Instance property, to avoid calling a constructor.Bander
Let us continue this discussion in chat.Semitropical
T
0

This syntax also works for databinding to static properties without generating the error (and I have no idea why):

DataContext={Binding Path=(prefix:TypeName.StaticPropertyName)}

Tomkin answered 29/1, 2019 at 22:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.