x:Static works as element but not as attribute with statics from project?!?

Answered x:Static works as element but not as attribute with statics from project?!?

  • domenica 17 settembre 2006 20:16
     
     

    I'm running Vista RC1 and playing with x:Static in elements and attributes and noticed a behavior that I'm not sure if it is by design or not. Here's the minimal repro:

    Start with a Window and let's use a static from the system as its title, using attribute syntax. (The static can come from any referenced assembly in this case, just not from the assembly being compiled):

    <Window x:Class="XamlTests.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    Title="{x:Static Member=s:Environment.CommandLine}"
    >
    </Window>

    This complies and works just as expected, showing the command line in the title of the window. While interesting, this is pretty much useless, so I want to show a string of my own, following the same static pattern, since I don't want to hardcode that string in the XAML as it will be calculated at runtime. For that, I create a static class with the static property:

    namespace XamlTests
    {
        public static class StaticData
        {
            public static string Hello { get { return "Hello World"; } }
        }
    }

    Then I reference this as my title, with the proper namespace changes:

    <Window x:Class="XamlTests.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:XamlTests;assembly=XamlTests"
    Title="{x:Static Member=c:StaticData.Hello}"
    >
    </Window>

    However, this fails to compile with this error:

    Window1.xaml(6,5): error MC3050: Cannot find the type 'StaticData'. Note that type names are case sensitive.

    Bummer! Does that mean that I can't use my own statics in XAML attributes? That doesn't seem right. On the other hand, if I use element syntax instead of attribute syntax it works, which makes the bug even more interesting:

    <Window x:Class="XamlTests.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:XamlTests;assembly=XamlTests"
    >
        <
    Window.Title>
            <
    x:Static Member="c:StaticData.Hello"/>
        </
    Window.Title>
    </
    Window>

    The end result is exactly what I want and the only downside is the extra markup to get it done.

    Sounds like a bug that the compiler can resolve the static call in elements but not in attributes.

    The other bummer is that only public classes/methods can be used with x:Static. If the static I want happens to be from the VS-generated Resources.resx file, that class is internal by default and XAML will barf that it is not public.

     

Tutte le risposte

  • lunedì 18 settembre 2006 17:09
     
     Con risposta

    Since the "c:" namespace is a reference to the local assembly -- that is, StaticData and Window1 are both in XamlTests.exe -- you don't need to specify the assembly name on the clr-namespace xmlns.  So this works for me:

        <Window x:Class="XamlTests.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:c="clr-namespace:XamlTests"
            Title="{x:Static Member=c:StaticData.Hello}" >

    The behavior still looks like a bug, so we'll investigate, but in the mean time it can simplify your markup.

    It should be possible to reference internal types as well.  For example here, I made the StaticData internal.  Are you only seeing a problem when it's in the Resources.resx file?

     

  • martedì 26 settembre 2006 05:45
     
     

    Cool, that worked as long as the property is public, even if the class itself is internal.

    With the class generated by the resx it doesn't work because the tool-generated property is also internal. If I manually make the property public then it works, but there's no such option in the resx visual designer. Resgen itself has /publicClass but that option is not exposed in the VS project for resx files.