Dr. Strangelove
Dr. Strangelove

Reputation: 3338

Binding inside binding WPF

I have a dictionary of items and I would like to show an aspect of items in a combobox - all in a MVVM pattern. In this regard, I define my Model as:

public class Model
{
    public Dictionary<UInt32, string> samples { set; get; }
}

and my ViewModel as:

internal class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        var smpls = new Dictionary<UInt32, string>();
        smpls.Add(1, "one");
        smpls.Add(2, "two");
        models = new Dictionary<string, Model>();
        models.Add("aKey", new Model() { samples = smpls });

        key = "aKey";
    }

    private Dictionary<string, Model> _models;
    public Dictionary<string, Model> models { set { _models = value; } get { return _models; } }

    private string _key;
    public string key { set { _key = value; OnPropertyChanged("key"); } get { return _key; } }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

Then I bind models to a combobox as:

<Grid>
    <ComboBox ItemsSource="{Binding Path=models[{Binding Path=key}].samples, Mode=OneTime}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <Border>
                    <StackPanel>
                        <TextBlock Text="{Binding Path=Value}" />
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</Grid>

I'm binding the Key of models dictionary to key property of viewModel which does not work. However, if I change the code as following everything works fine:

<ComboBox ItemsSource="{Binding Path=models[aKey].samples, Mode=OneTime}">

Upvotes: 3

Views: 4733

Answers (2)

Clemens
Clemens

Reputation: 128157

While models[aKey].samples is a valid property path, models[{Binding Path=key}].samples isn't. You might probably get around this limitation by using a MultiBinding with a appropriate value converter.

It would however by much easier to create an additional view model property like the CurrentSamples property shown below, which is updated whenever the key property changes:

public Dictionary<UInt32, string> CurrentSamples
{
    get { return models[key].samples; }
}

public string key
{
    get { return _key; }
    set
    {
        _key = value;
        OnPropertyChanged("key");
        OnPropertyChanged("CurrentSamples");
    }
}

Then bind the ItemsSource like this:

<ComboBox ItemsSource="{Binding CurrentSamples}">
    ...
</ComboBox>

Upvotes: 3

ΩmegaMan
ΩmegaMan

Reputation: 31721

I'm binding the Key of models dictionary to key property of viewModel which does not work.

Binding works by reflecting into a CLR structure. It uses the literal in the Path attribute to find, usually, a property on a CLR instance. The models[{Binding Path=key}] is not a proper path into a structure.

It isn't programmed to search for a binding in a binding; it takes the text as a literal for the path.

To quote MSDN Binding Sources Overview: For CLR properties, data binding works as long as the binding engine is able to access the binding source property using reflection.

So the second binding (Path=models[aKey].samples) works because you have provided a true pathed location to reflect off of and bind to.

Upvotes: 1

Related Questions