1
votes

I have a public class LPosition, which contains an attribute public String OZ { get; set; }. The application reads .txt and .xml files and OZ gets the values from these files. I need to bind OZ to comboBox:

<ComboBox x:Name="OZs" SelectionChanged="OZs_SelectionChanged" Margin="-10,0,10,1" Grid.Column="0" Grid.Row="1" Height="27" VerticalAlignment="Bottom">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding OZ}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

As you see, I have tried to implement data binding using DataTemplate, but it doesn't work. I know that it's possible to implement data binding with ItemsSource, but for this I need an ObservableCollection, which I don't have and I don't know how to create it from OZ. I have seen many examples where an ObservableCollection is hard coded, and I understand how to use it when it's hard coded, but I have no idea what to do in my case.
Sorry if the explanation is not clear, I'm very new to WPF. And I'm very lost with this problem. Any help would be appreciated.

edit: according to the answer of @Xiaoy312 I've added following code:

public IEnumerable<LPosition> OZList { get; set; } 

public FormelAssistent()
{
    InitializeComponent();
    this.DataContext = this;
    OZs.ItemsSource = OZList;
}

and XAML:

<ComboBox x:Name="OZs"
          SelectionChanged="OZs_SelectionChanged"
          Margin="-10,0,10,1"
          Grid.Column="0"
          Grid.Row="1"
          Height="27"
          VerticalAlignment="Bottom"
          ItemsSource="{Binding OZList}"
          DisplayMemberPath="OZ" />

But it doesn't work :(

2
You don't need an ObservableCollection to bind the ItemsSource property to. Any collection will do. However, it should be a collection, not a string. You should probably explain what exactly OZ is, and what the ComboBox should display.Clemens
@Clemens OZ is a string, it's one of the attributes of the class LPosition. What has to be displayed is the list of the values of OZ (it can be for example "1.01" or "1.1.01" etc., it is read from the file).java
You aren't using a dependency property, any sort of observable container, nor are you participating in the observer pattern by using INotifyPropertyChanged. Bindings do not poll objects for state changes, they expect to get notified of changes.Taekahn

2 Answers

0
votes

If you implement the INotifyPropertyChanged interface on your class like so, it should work.

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(string PropertyName = "")
{
    if(PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
    }
}

private IEnumerable<string> _oz;
public IEnumerable<string> Oz
{
    get
    {
        return _oz;
    }
    set
    {
        _oz = value;
        NotifyPropertyChanged("Oz");
    }
}

If you happen to be using a dependency object, you can instead use a dependency property. This would be my preferred option, given a choice.

public IEnumerable<string> Oz
{
    get { return (IEnumerable<string>)GetValue(OzProperty); }
    set { SetValue(OzProperty, value); }
}

public static readonly DependencyProperty OzProperty = DependencyProperty.Register("Oz", typeof(IEnumerable<string>), typeof(MainWindow), new PropertyMetadata(null));  

Its worth pointing out that if the container doesn't implement INotifyCollectionChanged (Such as ObservableCollection) then you will only see updates to the ComboBox when the entire list is replaced with an assignment.

If you really can't use ObservableCollection you could notify in the get and set.

0
votes

You need to provide a list of contents(options) for the ComboBox to choose from via its ItemsSource property. You don't necessarily need to back it with a ObservableCollection. Only if you plan to add/remove your collection while your view is being presented. Any IEnumerable could work too.

<ComboBox x:Name="OZs"
          ItemsSource="{Binding ListOrIEnumerableOfLPosition}"
          DisplayMemberPath="OZ" <- you can also use this instead of setting an item template, unless you need something complex
          ...>
    ...
</ComboBox >