2

-------EDIT------

So, i figured that my code is correct and so are the code snippets from all of your answers. Thanks for that. My problem is that my dev-maschine runs .NET4.5 which behaves differently! The very same program (compiled against .NET4.0) runs correct on a maschine with .NET4.0 but not on a maschine with .NET4.5!

So here is my revised question.

-------EDIT------

First, the simple example how i two-way bind my combobox to my data context:

View model:

public class MainWindowViewModel
{
    public List<String> MyElements { get; set; }
    public string SelectedElement { get; set; }

    public MainWindowViewModel()
    {
        MyElements = new List<string>() {"a", "b", "c"};
        SelectedElement = "a";
    }
}

and code-behind

private readonly MainWindowViewModel _viewModel = new MainWindowViewModel();
public MainWindow()
{
    InitializeComponent();
    DataContext = _viewModel;
}

and my xaml

<ComboBox
        ItemsSource="{Binding MyElements, Mode=OneWay}"
        SelectedItem="{Binding SelectedElement}" />

This works fine and if i select an item whith the combobox, it is bound to my view model.

OK, now i want to make my viewModel static but still two-way bind the selectedItem. I try this:

public class MainWindowViewModel
{
    public static List<String> MyElements { get; set; }
    public static string SelectedElement { get; set; }

    static MainWindowViewModel()
    {
        MyElements = new List<string>() {"a", "b", "c"};
        SelectedElement = "a";
    }
}

I do not need to set the datacontext in the Code-behind anymore and i know, that xaml needs an instance for two-way binding, so i have still the default constructor. I then bind the combobox

<Window.Resources>
    <me:MainWindowViewModel x:Key="model"/>
</Window.Resources>

<StackPanel>
    <ComboBox
        ItemsSource="{Binding Source={x:Static me:MainWindowViewModel.MyElements}, Mode=OneWay}"
        SelectedItem="{Binding Source={StaticResource model}, Path=SelectedElement}" />
</StackPanel>

The initial value is properly bound, but if i select another item with the combobox it it not reflected in my viewModel. What am i doing wrong?

EDIT:

If I use the exact same binding string for a TextBox and change the text in the box, it is reflected in the property.

<TextBox Text="{Binding Source={StaticResource model}, Path=SelectedElement}"/>

So obviously my binding string is correct but the way i use the combobox seems to be wrong. I also tried to bind SelectedValue instead... no change either.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Martin Booka Weser
  • 3,192
  • 5
  • 28
  • 41
  • Having checked your code again i have to say that it works for me. I've modified `public static string SelectedElement` to write trace output when the setter is called, and it gets called each time the selected item changes. You may still replace the `ItemsSource` binding by a static reference as @Baboon has suggested. – Clemens Jul 13 '12 at 11:31
  • Uh, i have .NET4.5 installed. May it be possible that sth has changed here? Of course i have a trace in my property, too. Just omitted it here for simplicity. And yes, i am aware that i usually implement INotifyPropertyChanged as well to bind back changes from the property to the ComboBox. – Martin Booka Weser Jul 13 '12 at 14:33

2 Answers2

4

Checked just in a sample project, works fine

public class ViewModel
{
    static ViewModel()
    {
        Items=new ObservableCollection<string>();
        SelectedItem = "222";
        Items.Add("111");
        Items.Add("222");
        Items.Add("333");
        Items.Add("444");
        Items.Add("555");
    }
    private static string _selectedItem;
    public static string SelectedItem
    {
        get { return _selectedItem; }
        set { _selectedItem = value;
            MessageBox.Show("Item " + value + " was selected");
        }
    }

    private static ObservableCollection<string> _items;
    public static ObservableCollection<string> Items
    {
        get { return _items; }
        set { _items = value; }
    }
}

and xaml

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:my="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="200" Width="300">
<Grid>
    <Grid.Resources>
        <my:ViewModel x:Key="viewM"/>
    </Grid.Resources>
    <ComboBox Height="23" HorizontalAlignment="Left" Margin="101,12,0,0" Name="comboBox1" VerticalAlignment="Top" Width="146" 
               ItemsSource="{Binding Source={x:Static my:ViewModel.Items}, Mode=OneWay}"
              SelectedItem="{Binding Source={StaticResource viewM}, Path=SelectedItem}" />
    </Grid>
</Window>

I have uploaded sample.

Artiom
  • 7,694
  • 3
  • 38
  • 45
  • just checked (not your attached 7z but copied your code snippet): Your MessageBox appears only once in the beginning. If i select another item in the checkbox, nothing happens and the SelectedItem property is not changed. – Martin Booka Weser Jul 13 '12 at 14:18
  • works everytime for me. Don't know what is wrong. Worked from first time – Artiom Jul 13 '12 at 18:36
  • Could you upload sample project to see what's happening there? – Artiom Jul 13 '12 at 18:39
2

You're being confused between instances and static properties: you don't need to bind a static object.

<ComboBox
        ItemsSource="{x:Static me:MainWindowViewModel.MyElements}"
        SelectedItem="{x:Static me:MainWindowViewModel.SelectedElement}" />

And you should implement INotifyPropertyChanged nevertheless.

Binding is about resolving the right instance from which you want to fetch data.
If there is no meaning of instance, there is no need for binding.

Louis Kottmann
  • 16,268
  • 4
  • 64
  • 88
  • Will this update the `MainWindowViewModel.SelectedElement` property when `ComboBox.SelectedItem` changes? I think the question here is the two-way aspect of the binding. – Clemens Jul 13 '12 at 11:08
  • Yes, it should. SelectedItem is 'TwoWay' by default. – Louis Kottmann Jul 13 '12 at 11:25
  • But you don't have a binding. `SelectedItem` surely *binds* two-way by default, but there is no two-way thing without a binding. – Clemens Jul 13 '12 at 11:40