Reputation: 1678
I keep getting this Error: System.Windows.Data Error: 40 : BindingExpression path error:
System.Windows.Data Error: 40 : BindingExpression path error:
'ViewModels' property not found on 'object' ''MainWindow' (Name='')'.
BindingExpression:Path=ViewModels.EventViewModel.EventName;
DataItem='MainWindow' (Name='');
target element is 'ComboBox' (Name='EventNameComboBox');
target property is 'SelectedItem' (type 'Object')
MainWindow.XAML
<ComboBox Name="EventNameComboBox"
DisplayMemberPath="EventName"
HorizontalContentAlignment="Center"
ItemsSource="{Binding Path=EventViewModels}"
materialDesign:HintAssist.Hint="Select an Event"
SelectionChanged="EventNameComboBox_SelectionChanged"
Width="400">
<ComboBox.SelectedItem>
<Binding Path="ViewModels.EventViewModel.EventName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<validationRules:EventNameValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
EventNameValidationRule.cs
public class EventNameValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
string eventName = value == null ? "" : value.ToString();
return string.IsNullOrEmpty(eventName)
? new ValidationResult(false, "Please select a Event")
: ValidationResult.ValidResult;
}
}
Finally,
EventViewModel.cs
public class EventViewModel : INotifyPropertyChanged
{
private int _eventId;
private string _eventName;
public int EventId
{
get { return _eventId; }
set
{
_eventId = value;
OnPropertyChanged("EventId");
}
}
public string EventName
{
get { return _eventName; }
set
{
_eventName = value;
OnPropertyChanged("EventName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I'm not sure what is going on.
UPDATE
MainWindow.xaml.cs
private List<EventViewModel> _eventViewModels;
public List<EventViewModel> EventViewModels
{
get { return _eventViewModels; }
set { _eventViewModels = value; OnPropertyChanged("EventViewModels"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public MainWindow()
{
InitializeComponent();
EventViewModels = new List<EventViewModel>();
int year = 2008;
for (int i = 1; i <= 10; i++)
{
EventViewModel viewModel = new EventViewModel();
viewModel.EventId = i;
viewModel.EventName = $"{year} Test Event";
++year;
EventViewModels.Add(viewModel);
}
DataContext = this;
}
Upvotes: 1
Views: 1323
Reputation: 2933
There are two things in your code that needs attention:
The binding path ViewModels.EventViewModel.EventName is incorrect. The binding path should be based on the binding or the DataContext of the control, which in your case is the MainWindow.xaml.cs and that class doesn't have a property "ViewModels.EventViewModel.EventName".
You cannot bind the EventName property to your SelectedItem because the SelectedItem should be bound to a type of EventViewModel because the item source is a list of EventViewModel
What you need to do:
public EventViewModel SelectedEvent
{
get { return _SelectedEvent; }
set { _SelectedEvent = value; OnPropertyChanged("SelectedEvent"); }
}
<ComboBox.SelectedItem>
<Binding Path="SelectedEvent" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:EventNameValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedItem>
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value == null)
return new ValidationResult(false, "Please select a Event");
if (value is EventViewModel eventVm)
{
string eventName = eventVm.EventName == null ? "" : value.ToString();
return string.IsNullOrEmpty(eventName)
? new ValidationResult(false, "Please select a Event")
: ValidationResult.ValidResult;
}
throw new Exception("Invalid binding!");
}
Upvotes: 1