0
votes

I've got a Combobox whose ItemTemplate is bound to a DataTemplate containing one of my custom label controls. All the custom control does is localize the content assigned to it.

The Combobox (when closed) will display the text of the first item selected. However when the selected item is changed, the display of the closed Combobox will not update. I know the actual selected item is updated because it's bound to a property that changes correctly. The only problem is the display text.

So for instance if I select the item with text 'Item 1' the closed Combobox will display 'Item 1'. Then if I select 'Item 2' the closed Combobox will still display 'Item 1'.

Here's how it's set up ('Name' is a property of the items being bound in the ItemsSource):

<Grid.Resources>
    <DataTemplate x:Key="MyTemplate">
        <MyCustomLabel Content="{Binding Name}" />
    <DataTemplate>
</Grid.Resources>

<Combobox ItemsSource="{Binding MyItems}" ItemTemplate="{StaticResource MyTemplate}" />

Below is the code for my label control:

public class MyLabel : Label
{
    /// <summary>
    ///   When reassigning content in the OnContentChanged method, this will prevent an infinite loop.
    /// </summary>
    private bool _overrideOnContentChanged;

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        // if this method has been called recursively (since this method assigns content)
        // break out to avoid an infinite loop
        if (_overrideOnContentChanged)
        {
            _overrideOnContentChanged = false;
            return;
        }

        base.OnContentChanged(oldContent, newContent);

        var newContentString = newContent as string;
        if (newContentString != null)
        {
            // convert the string using localization
            newContentString = LocalizationConverter.Convert(newContentString);

            // override the content changed method
            // will prevent infinite looping when this method causes itself to be called again
            _overrideOnContentChanged = true;
            Content = newContentString;
        }
    }
}

Any advice would be greatly appreciated. Thanks!

1
It's not the label that's supposed to change in the combo-box. The combo-box will generate a label for each item in the ItemsSource.Maciek

1 Answers

0
votes

Perform a 2-way databinding on the SelectedItem property of the combo box.

The target property that you're binding the combo-box to - should raise a PropertyChanged event.

<ComboBox ItemsSource={Binding Path=Source} SelectedItem={Binding Path=CurrentItem, Mode=TwoWay}/>


class ComboContext : INotifyPropertyChanged
{
public List<object> Source { get; set; } // attach your source here
public object CurrentItem { get { return mCurrentItem; } set { mCurrentItem = value; OnPropertyChanged("CurrentItem"); } } // bind to this property
private object mCurrentItem;

void OnPropertyChanged(string name)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}

The code sample might not be "complete" - it's 1am and I'm kinda tired, but it should put you on the right track.

Edit2.

Just noticed your template, it's wrong, the whole idea is wrong.

<ComboBox ItemsSource={Binding Path=Source} SelectedItem={Binding Path=CurrentItem, Mode=TwoWay}>
    <ComboBox.ItemTemplate>
        <DataTemplate>
        <Grid>
            <TextBlock Text={Binding}/>
        </Grid>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Notice that the texblock's text is a binding with no path, (and it's a default binding too.) the no-path binding means that this textblock will bind to whatever is directly "underneath".