简体   繁体   中英

WPF: comboBox data binding issue

I have a public class LPosition , which contains an attribute public String OZ { get; set; } public String OZ { get; set; } 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 :(

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 >

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM