I know this has been asked times before but none of the solutions so far works for me. I try to bing an ObservableCollection
to the ItemsSource
propery of a combobox but fail miserably.
The ObservalbeCollection is part of the Window.cs:
public partial class RecordSoundWindow2 : Window
{
public ObservableCollection<string> RecordingDevices { get; set; }
public RecordSoundWindow2()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
RecordingDevices = new ObservableCollection<string>();
for (int n = 0; n < WaveIn.DeviceCount; n++)
{
RecordingDevices.Add(WaveIn.GetCapabilities(n).ProductName);
}
}
I certainly know that it gets updated with my microphone name, but the combobox never shows its contents. I've tried the following approaches so far:
<ComboBox DockPanel.Dock="Top" Name="cbDevices" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=RecordingDevices}"/>
<ComboBox DockPanel.Dock="Top" Name="cbDevices" ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=RecordingDevices}"/>
<ComboBox DockPanel.Dock="Top" Name="cbDevices" ItemsSource="{Binding Path=RecordingDevices}"/>
I've seen many answers where the RealtiveSource
with FindAncestor
works, but not for me. What am I missing here?
You need to change your property to a Dependency Property
. Your bindings will not work unless you set the DataContext
.
In your case, your are inheriting from a Window
, therefore a DependencyProperty
is the correct way to go.
public ObservableCollection<string> RecordingDevices
{
get { return (ObservableCollection<string>)GetValue(RecordingDevicesProperty); }
set { SetValue(RecordingDevicesProperty, value); }
}
// Using a DependencyProperty as the backing store for RecordingDevices. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RecordingDevicesProperty =
DependencyProperty.Register("RecordingDevices", typeof(ObservableCollection<string>), typeof(RecordSoundWindow2), new PropertyMetadata(null));
Mike Eason's answer works.
However Clemens' INotifyPropertyChanged
approach is cleaner and I prefer it so I am posting this as answer.
This is the XAML:
<ComboBox Name="cbDevices" Width="200"
SelectionChanged="cbDevices_SelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=RecordingDevices}"/>
Following is the code behind with a solution I found on another answer for a better INotifyPropertyChanged
approach where the Property name is not given as string, allowing for better renaming of variables afterwards:
public partial class RecordSoundWindow : Window, INotifyPropertyChanged
{
private IAudioRecorder Recorder;
public ObservableCollection<string> RecordingDevices { get; set; }
public RecordSoundWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
InitRecorder();
}
private void InitRecorder()
{
RecordingDevices = new ObservableCollection<string>();
Recorder = new AudioRecorder();
for (int n = 0; n < WaveIn.DeviceCount; n++)
{
RecordingDevices.Add(WaveIn.GetCapabilities(n).ProductName);
OnMyPropertyChanged(() => RecordingDevices);
}
//cbDevices.ItemsSource = RecordingDevices;
if (RecordingDevices.Count > 0)
cbDevices.SelectedIndex = 0;
Recorder.SampleAggregator.MaximumCalculated += OnRecorderMaximumCalculated;
}
public event PropertyChangedEventHandler PropertyChanged;
// Raise the event that a property has changed in order to update the visual elements bound to it
internal void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
//Converts the passed parameter to its name in string
internal void OnMyPropertyChanged<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
OnPropertyChanged(expressionBody.Member.Name);
}
}
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.