views:

119

answers:

4

I am trying to bind to a static property on a static class, this property contains settings that are deserialized from a file.

It never works with the following XAML :

    <Window.Resources>
    <ObjectDataProvider x:Key="wrapper" ObjectType="{x:Type Application:Wrapper}"/>
</Window.Resources>

<ScrollViewer x:Name="scrollViewer" ScrollViewer.VerticalScrollBarVisibility="Auto"DataContext="{Binding Source={StaticResource wrapper}, UpdateSourceTrigger=PropertyChanged}">

   <ComboBox x:Name="comboboxThemes"
                  SelectedIndex="0"
                  SelectionChanged="ComboBoxThemesSelectionChanged"
                  Grid.Column="1"
                  Grid.Row="8"
                  Margin="4,3" ItemsSource="{Binding Settings.Themes, Mode=OneWay}" SelectedValue="{Binding Settings.LastTheme, Mode=TwoWay}"   />

It does work by code however :

comboboxThemes.ItemsSource = Settings.Themes;

Any idea ?

Thank you :-)

+2  A: 

XAML:

<Window x:Class="StaticTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:StaticTest="clr-namespace:StaticTest"
    Height="300" Width="300">
    <StackPanel>
        <TextBlock Text="{x:Static StaticTest:MyStaticStuff.MyProp}" />
    </StackPanel>
</Window>

Code behind:

namespace StaticTest
{
    public static class MyStaticStuff
    {
        public static string MyProp { get { return "From static"; } }
    }
}
Wallstreet Programmer
+5  A: 

Your code-behind doesn't perform a binding, it directly assigns a source to the ComboBox...

If you want to do the same in XAML, you don't need a binding at all, you just need the StaticExtension markup extension :

ItemsSource="{x:Static local:Settings.Themes}"

(where local is the xmlns mapping for the namespace containing the Settings class)

Thomas Levesque
A: 

For the ItemsSource you can use a direct x:Static assignment as shown in the other answers but for the SelectedValue you need a Binding, which requires an instance on which to set a property. You should be able to restructure the static class into a Singleton to provide a bindable instance and property which can still be referenced statically from code, something like:

public class Settings : INotifyPropertyChanged
{
    public static Settings Instance { get; private set; }

    public static IEnumerable<string> Themes { get; set; }

    private string _lastTheme;
    public string LastTheme
    {
        get { return _lastTheme; }
        set
        {
            if (_lastTheme == value)
                return;
            _lastTheme = value;
            PropertyChanged(this, new PropertyChangedEventArgs("LastTheme"));
        }
    }

    static Settings()
    {
        Themes = new ObservableCollection<string> { "One", "Two", "Three", "Four", "Five" };
        Instance = new Settings();
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Then the ComboBox would use these bindings:

<ComboBox ItemsSource="{x:Static local:Settings.Themes}"
SelectedValue="{Binding Source={x:Static local:Settings.Instance}, Path=LastTheme}"   />
John Bowen
Thank you all, I've tried everything you said, it doesn't work; in fact I did try that route already.When I create a small test project, it works fine; for odd reasons on this one it doesn't and it's too huge so I can post the code; I think I am going to rewrite this whole part.What I've found however is an "Exception has been thrown by the target of an invocation" occurs through IntelliSense/Resharper, i don't know really as I am unable to debug furthermore this step.Thank you,
Thank you all !
+1  A: 

I have found the answers !

It did silently throw an Exception has been thrown by the target of an invocation i didn't know more ...

I was initializing a log that writes to a file; the designer finally showed up the details of the exception, it was looking for creating the file in Visual Studio directory which is in Program Files, hence a security exception was thrown.

Apparently VS copies the file to its folder, for its Designer.

I fixed it like this :

 var isInDesignMode = DesignerProperties.GetIsInDesignMode(SettingsWindow);
        if (!isInDesignMode)
        {
            Log = new WrapperLogManager("log_wrapper.txt");
        }

Last but not least, using ObjectDataProvider never worked as well, only through x:Static

This was driving me totally crazy for a few days as it's not so hard to bind data; I just learned another lesson !

Also, I have design-time preview now as well !